如何访问 pod 元数据
我们在 pod 中运行容器的时候,是否也会有想要获取当前 pod 的环境信息呢?咱们写的 yaml 清单写的很简单,实际上部署之后, k8s 会给我们补充在 yaml 清单中没有写的字段,那么我们的 pod 环境信息和容器的元数据如何传递到容器中呢?是不是也是通过获取这些 k8s 默认给我填写的字段呢?
有 3 种方式:
- 通过环境变量的方式
- 通过 Downward Api 的方式
- 通过和 ApiServer 交互的方式
通过环境变量的方式
通过环境变量的方式获取 pod 的信息,还是比较简单的,还记得我们之前将卷中的数据转成环境变量传入到容器中的方式吗?
本次我们也是使用类似的方式来传递数据,应该说比之前的还要简单,不过我们本次传递的是环境信息,例如 pod 的 IP,pod 的 名称,命名空间,pod 所属的服务账号,节点的名称,CPU / 内存的请求 / 限制大小等等
来我们任意看一下 pod 的 yaml 清单信息
[图片上传失败...(image-c583e6-1689691899710)]
[图片上传失败...(image-e9c644-1689691899710)]
[图片上传失败...(image-9c6415-1689691899710)]
上述 yaml 清单信息中,每一个字段我们都可以用来传递到容器中作为环境变量,我们可以来尝试写一个
- 写一个 yaml 清单,创建名称为 my-downward 的 pod
- 容器里面的使用 busybox 作为基础镜像,由于容器需要运行在 pod 中,因此我们需要运行一个程序在容器中,例如 sleep 8888888 或者其他的任意一个可以长期运行的程序
[图片上传失败...(image-313a56-1689691899710)]
apiVersion: v1
kind: Pod
metadata:
name: my-downward
spec:
containers:
- name: my-downward
image: busybox
command: ["sleep","8888888"]
env:
- name: XMT_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: XMT_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: XMT_NODENAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: XMT_SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
- name: XMT_REQUEST_CPU
valueFrom:
resourceFieldRef:
resource: requests.cpu
divisor: 1m
- name: XMT_LIMITS_MEMORY
valueFrom:
resourceFieldRef:
resource: limits.memory
divisor: 1Ki
上述自己配置了多个 XMT_* 的环境变量,来源都是在 pod 中的对应配置,kubectl create 上述 yaml 文件后,可以查看效果如下
[图片上传失败...(image-15a79b-1689691899710)]
环境变量如上所示,当我们容器里面需要使用该环境变量的时候,就可以随取随用了,很方便
可以看到容器中的环境变量和 yaml 清单上的 env 一一对应
[图片上传失败...(image-676135-1689691899710)]
通过 Downward Api 卷的方式
当然,我们也可以使用第二种方式,那就是通过 Downward Api 卷的方式,具体的操作方式和上述环境变量的方式类似,但是使用卷的方式,会在指定的路径下生成文件
Downward Api 看上去会不会想起 Restful Api,是不是都是通过访问接口的方式获取数据呢?
并不是这样的, Downward Api 实际上是将 pod 的定义和状态信息,作为容器的环境变量或者文件的方式,来给容器传递数据的,如图
[图片上传失败...(image-e82265-1689691899710)]
Downward Api 卷的方式可以这么写:
apiVersion: v1
kind: Pod
metadata:
name: my-downward-vv
labels:
xmtconf: dev
spec:
containers:
- name: my-downward-vv
image: busybox
command: ["sleep","8888888"]
volumeMounts:
- name: my-downward-vv
mountPath: /etc/myvv
volumes:
- name: my-downward-vv
downwardAPI:
items:
- path: "xmtPodName"
fieldRef:
fieldPath: metadata.name
- path: "xmtNamespace"
fieldRef:
fieldPath: metadata.namespace
- path: "xmtLabels"
fieldRef:
fieldPath: metadata.labels
看这个 yaml 还是比较简单的,和写挂载的方式类似的,此处使用 downwardAPI 下的 items,来传递每一个数据,数据的来源写法和上述的环境变量类似
[图片上传失败...(image-8712d-1689691899710)]
我们可以看到,Downward Api 挂载数据,具体的文件里面会以键值对的方式来呈现,也会以文本的形式来呈现
我们来将 pod 的标签修改成 prod,验证容器里面对应的文件是否会对应修改?
kubectl label pod my-downward-vv xmtconf=prod --overwrite
[图片上传失败...(image-788f11-1689691899710)]
进入容器中查看 /etc/myvv/xmtLabels
文件是否有变化
[图片上传失败...(image-57a1e2-1689691899710)]
通过上述效果,可以看出,当使用 Downward Api 卷的时候,对应的环境变量会以文件的形式存在于我们指定的目录下
若我们在程序运行中修改了环境变量对应的值,那么卷中的文件内容也会相应修改
如何与 APiServer 进行交互?
既然可以用第三种方式与 ApiServer 的方式,咋还使用环境变量和 Downward Api 的方式呢?
自然是因为 Downward Api 的方式有所局限,局限就是 Downward Api 的方式只能获取自身 pod 的数据,如果我们想获取其他 pod 的资源信息,这个时候我们就需要和 Api Server 进行交互了
类似于这样:
[图片上传失败...(image-5e5328-1689691899710)]
那么我们来写一个 pod, 让 pod 里面的容器与 ApiServer 进行交互,此处我们需要注意两点:
- 我们要确定 ApiServer 的位置,我们才能有机会正确访问到
- 需要通过 ApiServer 的认证
咱们写一个 pod ,用于在这个 pod 里面使用 curl 访问 ApiServer
自己制作一个简单的带有 curl 的镜像
FROM ubuntu:latest
RUN apt-get update -y
RUN apt install curl -y
ENTRYPOINT ["sleep", "8888888"]
制作该镜像,推送镜像到 dockerhub
docker build -t xiaomotong888/xmtcurl .
docker push xiaomotong888/xmtcurl
写一个简单的 yaml,运行 pod
mycurl.yaml
apiVersion: v1
kind: Pod
metadata:
name: xmt-curl
spec:
containers:
- name: xmt-curl
image: xiaomotong888/xmtcurl
command: ["sleep","8888888"]
pod 运行成功后,咱们进入到 容器里面
kubectl exec -it xmt-curl bash
咱们可以在 k8s 环境中查看一下 kubernetes 服务的 ip ,我们可以这样来访问
[图片上传失败...(image-f7e351-1689691899710)]
在容器中访问 kubernetes
[图片上传失败...(image-fdc1ea-1689691899710)]
这是因为没有证书,我们需要导入证书和 token , 这样才能正确的访问到 ApiServer,并且还需要一个重要的操作
创建一个 clusterrolebinding,需要创建了该绑定之后,才能正常的访问到 ApiServer,若没有创建该绑定,那么后面的步骤都做好了,ApiServer 也会报 403 Forbidden
kubectl create clusterrolebinding gitlab-cluster-admin --clusterrole=cluster-admin --group=system:serviceaccounts --namespace=dev
证书的位置还记的吗?
[图片上传失败...(image-b68545-1689691899710)]
之前我们查看过默认的 k8s 挂载的位置,/var/run/secrets/kubernetes.io/serviceaccount
这里面有 命名空间,证书,token
[图片上传失败...(image-d2ce09-1689691899710)]
这个时候,我们访问 k8s ApiServer 的时候,可以加上该证书
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://kubernetes
我们可以导入一个环境变量,访问 k8s ApiServer 的时候就不需要收到导入证书了
export CURL_CA_BUNDLE=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
https://gitee.com/common_dev/mypic20220206/raw/master/image-20220204152125059.png
可以看到效果和刚才不一样了,现在报 403 是因为没有 token ,这个时候,我们在加上 token 即可
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
[图片上传失败...(image-876451-1689691899710)]
这样就可以看到 apiServer 都有哪些 api 了 , 这些 api 可都是我们在写 yaml 清单时候 apiVersion 的是时候填写的
那么用一个图来结束今天的分享
[图片上传失败...(image-45914-1689691899710)]
容器里面的应用通过证书与 ApiServer 完成认证,通过 token 和 namespace 和 ApiServer 完成接口的交互
今天就到这里,学习所得,若有偏差,还请斧正
欢迎点赞,关注,收藏
朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力
[图片上传失败...(image-6e2291-1689691899710)]
好了,本次就到这里
技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。
我是阿兵云原生,欢迎点赞关注收藏,下次见~
网友评论