【K8S in Action】第八章 从应用访问pod元数据

通过环境变量或者configMap和secret卷向应用传递配置数据。这对于pod调度、 运行前预设的数据是可行的。
对于那些不能预先知道的数据, 比如pod的IP、 主机名或者是pod自身的名称。经在别处定义的数据, 比如pod的标签和注解。不想在多个地方重
复保留同样的数据。

通过Downward API传递元数据

1 了解可用的元数据

Downward API 允许我们通过环境变量或者文件(在downwardA釭卷中)的传递pod的元数据。这种方式主要是将在pod的定义和状态中取得的数据作为环境变量和文件的值, 如图所示
【K8S in Action】第八章 从应用访问pod元数据_第1张图片
• pod的名称
• pod的IP
• pod所在的命名空间
• pod运行节点的名称
• pod运行所归属的服务账户的名称
• 每个容器请求的CPU和内存的使用量
• 每个容器可以使用的CPU和内存的限制
• pod的标签
• pod的注解

2 通过环境变量暴露元数据

通过环境变量的方式将pod和容器的元数据传递到容器中。

pod的名称 、IP和命名空间可以通过POD_NAME、 POD_IP和POD_NAMESPACE 这几个环境变量分别暴露。

apiVersion: vl 
kind: Pod 
metadata: 
	name: downward 
spec: 
	containers: 
	- name: main 
	image: busybox 
	command: ["sleep", "9999999") 
	resources:
		requests: 
			cpu: 15m 
			memory: lOOKi 
		limitS:
			cpu: 100m 
			memory: 4Mi 
	env: 
	- name: POD_NAME
		valueFrom:
			fieldRef: 
				fieldPath: metadata.name     引用pod manifest中的元数据名称字段 
	- 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:            容器请求的内存和CPU 是 resourceFieldRef 字段
				resource: requests.cpu 
				divisor: lm               资源相关的字段,基数单位
	- name: CONTAINER MEMORY LIMIT KIBIBYTES
		valueFrom:
			resourceFieldRef: 
				resource: limits.memory
				di visor: lKi

看看容器中出环境变量
kubect1 exec downward env

3 通过downwardAPI卷来传递元数据

如果更倾向于使用文件的方式而不是环境变量的方式暴露元数据,可以定义一个downwardAPI卷并挂载到容器中。必须使用downwardAPI卷来暴露pod标签或注解。

apiVersion: vl 
kind: Pod 
metadata:
	name: downward 
	labels: 
		foo: bar 
	annotations:
		keyl: valuel 
		key2: |      通过downwardAPI卷来暴露这些标签和注解
			multi
			line 
			value 
spec: 
	containers: 
	- name: main
		image: busybox
		command: ["sleep", "9999999"]
		resources:
			requests: 
				cpu: 15m 
				memory: lOOKi 
			limitS:
				cpu: 100m 
				memory: 4Mi 
		volumeMountS:                     在/etc/downward 目录下挂载这个dowanward卷
		- name: downward
		  mountPath: /etc/downward
	volumes: 
		- name: downward          通过将卷的名字设定为downward来定义—个dowanwardAPI卷
		downwardAPI:
			items: 
			- path: "podName"       pod的名称(来自manifest文件中 的metadate.name字段)将被写入
			  fieldRef:
				fieldPath: metadata.name 
			- path: "podNamespace"
			  fieldRef:
				fieldPath: metadata.namespace
				
			- path: "labels"                  pod的标签将被保存到/etc/dowanward/labels文件中 
			  fieldRef:
				fieldPath: metadata.labels
				
			- path:"annotations"            pod的注解将被保存到/etc/dowanward/annotations 文件中
				fieldRef:
					fieldPath: metadata.annotations 
			- path: "containerCpuRequestMilliCores"
				resourceFieldRef:
					containerName: main 
					resource: requests.cpu 
					divisor: lm 
			- path: "containerMemoryLimitBytes"
				resourceFieldRef: 
					containerName: main 
					resource: limits.memory
					divisor: 1	


$ kubectl exec downward cat /etc/downward/labels 
foo="bar"
  • 可以在pod运行时修改标签和注解。如我们所愿,当标签和注解被修改后,Kubemetes会更新存有相关信息的文件,从而使pod可以获取最新的数据。
  • 在环境变量方式下,一旦标签和注解被修改,新的值将无法暴露。

当暴露容器级的元数据时,如容器可使用的资源限制或者资源请求(使用字段 resourceFieldRef), 必须指定引用资源字段对应的容器名称。因为我们对千卷的定义是基于 pod级的,而不是容器级的。

spec: 
	volumes: 
	- name: downward
		downwardAPI:
			items: 
			- path: "containCpuRequestMilliCores"
			  resourceFieldRef: 
				containerName: main          必须指定容器名称
				resource: requests.cpu 
				divisor: lm

二、 与Kubernetes API服务器交互

通过服务相关的环境变量或者 DNS 来获取服务和 pod的信息, 但如果应用需要获取其他资源的信息或者获取最新的信息, 就需要直接与API 服务器进行交互。

2.1 Kubernetes REST API

可以通过运行kubectl cluster-info 命令来得到服务器的 URL。kubectl proxy命令启动了一个代理服务来接收来自你本机的 HTTP 连接并转发至 API 服务器, 同时处理身份认证。

$ kubect1 cluster-info
Kubernetes master is running at https://192.168.99.100:8443

$ kubect1 proxy 
Starting to serve on 127.0.0.1:8001

curl http://localhost:8001/apis/batch

curl http://localhost:8001/apis/batch/vl


通过名称恢复一个指定命名空间下的资源 (name:my-job;namespace:dfault)
curl http://localhost:8001/apis/batch/vl/namespaces/default/jobs/my-job 
与这个Job资源的完整的 JSON 定义信息一致
kubetcl get job my-job -o json

通过在 /apis/batch/vl/jobs路径运行一个GET请求,列举集群中所有的Job实例。

2.2 从pod内部与API服务器进行交互

apiVersion: vl 
kind: Pod 
metadata:
	name: curl 
spec: 
	containers: 
	- name: main 
		image: tutum/curl
		command: ["sleep", "9999999"]

在完成pod的创建后,在容器中运行kubectl exec来启动一个bashshell
kubectl exec -it curl bash

  • 确定API 服务器的位置
  • 确保是与 API 服务器进行交互,而不是一个冒名者
  • 通过服务器的认证,否则将不能查看任何内容以及进行任何操作
确定API 服务器的位置

Kubemetes API服务器的 IP 地址和端口:名为kubernetes的服务在默认的命名空间被自动暴露。每个服务都被配置了对应的环境变量, 在容器内通过查询KUBERNETES_SERVICE_HOST 和 KUBERNETES_SERVICE_PORT 这两个环境变量就可以获取 API 服务器的 IP 地址和端口。

同样, 每个服务都可以获得一个 DNS 入口,curl 指向 https://kubemetes

kubectl get SVC 
NAME      CLUSTER-IP EXTERNAL-IP  PORT(S)   AGE 
kubernetes 10.0.0.1   <none>    443/TCP     46d

curl https://kubernetes
验证服务器身份

在讨论 Secret 时, 我们看到一个名为 defalut-token-xyz的 Secret 被自动创建,并挂载到每个容器的 /var/run/secrets/kubemetes.io/serviceaccount
目录下。curl允许使用-cacert选项来指定CA 证书。

在容器内执行
curl --cacert /var/run/secrets/kubernetes.io/serviceaccountca.ert https://kubernetes
Unauthorized 

设置CURL_CA_BUNDLE环境变量来简化操作,不用每次指定 cacert 
 export CURL_CA_BUNDLE=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
获得API服务器授权

凭证可以使用之前提到的default-token Secret来产生, 同时凭证可以被存放在secret卷的token文件中。

TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
Authorization字段向 API 服务器传递了凭证
curl -H "Authorization: Bearer $TOKEN"  https://kubernetes

secret卷中命名空间的文件,可以读取这个文件来获得命名空间信息
NS=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) 
curl -H "Authorization: Bearer $TOKEN"  https://kubernetes/api/vl/namespaces/$NS/pods

三、通过 ambassador 容器简化与 API 服务器的交互

可以在主容器运行的同时, 启动一个ambassador容器,并在其中运行kubecctl proxy命令, 通过它来实现与API服务器的交互。保证安全性的前提下有办法简化通信的方式。

apiVersion: vl 
kind: Pod 
metadata:
	name: curl 
spec: 
	containers: 
	- name: main 
		image: tutum/curl
		command: ["sleep", "9999999"]
	- name: ambassador 
		image: luksa/kubectl-proxy:l.6.2

pod包含两个容器,使用-c main选项指定
 kubectl exec -it curl-with-ambassador -c main bash
 curl localhost:8001
 成功了

curl向在ambassador容器内运行的代理发送普通的 HTTP 请求(不包含任何授权相关的标头), 然后代理向 API 服务器发送 HTTPS 请求, 通过发送凭证来对客户端授权, 同时通过验证证书来识别服务器的身份。

四 使用客户端库与API服务器交互

可以使用一个标准的客户端库来执行简单的 HTTP 请求。

你可能感兴趣的:(部署与运维篇,kubernetes,java,容器)