前面我们从pod的原理到生命周期介绍了pod的一些使用,作为kubernetes中最核心的对象,最基本的调度单元,我们可以发现pod中的属性还是非常繁多的,前面我们使用过一个volumes的属性,表示声明一个数据卷,我们可以通过命令kubectl explain pod.sec.volumes去查看该对象下面的属性非常多,前面我们只是简单的使用了hostpath和empryDir{}这两种模式,其中还有一种叫做downwardAPI这个模式和其他模式不一样的地方在于它不是为了存放容器的数据也不是用来进行容器和宿主机的数据交换的,而是让pod里的容器能够直接获取到这个pod对象本身的一些信息。
downwardAPI提供了两种方式用于将pod的信息注入到容器内部:
环境变量: 用于单个变量,可以将pod信息和容器信息直接注入容器内部
volume挂载:将pod信息生成为文件,直接挂载到容器内部中去
环境变量
我们通过downwardAPI来讲pod的ip,名称以及所对应的namespace注入到容器的环境变量中去,然后再容器中打印全部的环境变量来进行验证
[root@master1 ~]# cat env-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: env-pod
namespace: kube-system
spec:
containers:
- name: env-pod
image: busybox
command: ["/bin/sh", "-c","env"]
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
我们可以看到上面我们使用了一种新到方式来设置env的值,valueFrom,由于pod的name和namespace属于元数据,是在pod创建之前就已经定下来的,所以我们可以使用metadata就可获取到,但是对于pod的IP则不一样,因为我们知道pod ip是不固定的,pod重建了就变了,它属于状态数据,所以我们使用status这个属性去获取,另外出了使用fieldRef获取pod的基本信息,还通过resourceFieldRef去获取容器的资源请求和资源限制信息。

kubectl create -f env-pod.yaml

kubectl logs env-pod -n kube-system | grep POD
kubectl logs -f env-pod -n kube-system
[root@master1 ~]# kubectl logs env-pod -n kube-system
POD_IP=10.244.2.38
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
KUBE_DNS_SERVICE_PORT_DNS_TCP=53
HOSTNAME=env-pod
SHLVL=1
HOME=/root
KUBE_DNS_SERVICE_HOST=10.96.0.10
KUBE_DNS_PORT_9153_TCP_ADDR=10.96.0.10
KUBE_DNS_PORT_9153_TCP_PORT=9153
KUBE_DNS_PORT_9153_TCP_PROTO=tcp
KUBE_DNS_SERVICE_PORT=53
KUBE_DNS_PORT=udp://10.96.0.10:53
POD_NAME=env-pod
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBE_DNS_PORT_53_TCP_ADDR=10.96.0.10
KUBERNETES_PORT_443_TCP_PORT=443
KUBE_DNS_SERVICE_PORT_METRICS=9153
KUBE_DNS_PORT_9153_TCP=tcp://10.96.0.10:9153
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBE_DNS_PORT_53_UDP_ADDR=10.96.0.10
KUBE_DNS_PORT_53_TCP_PORT=53
KUBE_DNS_PORT_53_TCP_PROTO=tcp
KUBE_DNS_PORT_53_UDP_PORT=53
KUBE_DNS_SERVICE_PORT_DNS=53
KUBE_DNS_PORT_53_UDP_PROTO=udp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
POD_NAMESPACE=kube-system
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
KUBE_DNS_PORT_53_TCP=tcp://10.96.0.10:53
KUBE_DNS_PORT_53_UDP=udp://10.96.0.10:53
我们可以看到pod 的ip ,name,namespace都通过环境变量打印出来的
kubectl get svc -n kube-system

volume挂载
downward API除了提供环境变量方式外,还提供通过volume挂载的方式去获取pod的基本信息,接下来通过 downward API将pod的label,annotation等信息通过volume挂载到容器的某个文件中去,然后在容器中打印机出的值来验证的,对应的资源清单
apiVersion: v1
kind: Pod
metadata:
name: volume-pod
namespace: kube-system
labels:
k8s-app: test-volume
node-env: test
annotations:
own: wangmuniangniang
bulid: test
spec:
volumes:
- name: podinfo
downwardAPI:
items:
- path: labels
fieldRef:
fieldPath: metadata.annotations
- path: anntations
fieldRef:
fieldPath: metadata.annotations
containers:
- name: volume-pod
image: busybox
args:
- sleep
- "3600"
volumeMounts:
- name: podinfo
mountPath: /etc/podinfo
我们将元数据labels和annotaions以文件的形式挂载到/etc/podinfo目录下,创建上面的pod

创建成功后,我们可以进入容器中查看元信息是不是已经存入到文件中了

[root@master1 ~]# kubectl exec -it volume-pod /bin/sh -n kube-system
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # ls /etc/podinfo/
anntations labels
/ # ls
bin dev etc home proc root sys tmp usr var
/ # cat /etc/podinfo/labels
bulid="test"
kubernetes.io/config.seen="2022-04-27T03:23:02.840574876-04:00"
kubernetes.io/config.source="api"
own="wangmuniangniang"/ # ^C
/ #
可以看到pod的labels和annotations信息都被挂载到/etc/podinfo目录下面lables和annotations文件了 目前downwardAPI支持的字段已经非常丰富了
DownwardAPI支持的字段已经非常丰富了,比如
fieldRef可以声明使用
spec.nodeName 宿主机的名字
status.hostIP 宿主机ip
metadata.name pod的名字
metadata.namespace pod的Namespace
status.podIP pod的ip
spec.serviceAccountName pod的service Account的名字
metadata.uid pod的UID
metadata.labels 指定key的label值
metadata.annotations 指定key的annotation值
metadata.labels pod的所有label
mwetadata.annotations pod的所有的annotation
使用 resourceFieldRef可以声明使用
容器cpu limit cpu requesr memory limit memory request
需要注意的是downwardAPI能够获取到的信息,一定是pod里的容器进程启动之前就能够确定袭下来的信息,而如果想要获取pod容器运行后才会出现信息,比如容器进程的PID,那肯定不能使用downwardAPI,而应该考虑在pod里定义了一个sidecar容器来获取了
在实际应用中,如果你的应用有获取pod的基本信息需要,一般我们就可以利用downwardAPI来获取基本信息,然后编写一个启动脚本或者利用initcontainer将pod的信息注入到我们的容器中去,然后再我们自己的应用中就可以正常的处理相关逻辑了
除了通过dowenwardAPI客户可以获取pod本身的信息之外,其实我们还可以通过映射其他资源对象来获取对应的信息,比如secret,configMap资源对象,同样我们可以通过环境变量和挂载volume的方式来获取他们的信息,但是通过环境变量获取这些信息的方式,不具备自动更新的能力,所以一般情况下,都建议使用volume文件的方式获取这些信息,因为通过voulme的方式挂载文件在pod中会进行热更新
podpreset
我们已经学些了很多pod的知识点,但是可能有部分同学还觉得pod的字段属性太多了。kubernetes能提供一个功能为pod自动填充一些字段呢,这个需求还是很实际的,
kubernetes版本后提供了一个叫做podpreset的功能可以解决
kubernetes提供了一个podpreset准入控制器,当启用后,podpreset会将应用创建请求传入到该控制器上,当有pod创建请求时,系统将执行一下操作。
检索所有可用的podpreset
检查有podpreset的标签选择器上的标签与正在创建的pod的标签是否匹配
尝试将有podpreset定义的各种资源合并到正在创建的pod中
出现错误时,该pod上引发记录合并错误的时间,podPreset不会注入任何资源到创建的pod中
注释刚生成的修改过的pod spec以表明她已被podprese修改过,
每个pod可以匹配podPres、et并且每个podpreset可以应用于多个pod,podpreset应用于kubernetes会修改pod spec,对于env,envfrom和volumeMounts的修改,kubernetes修改pod中所有容器的spec,对于volume的更改,kubernetes修改pod spec
启用podpreset
要启用podpreset功能,需要确保你使用的是kubernetes1.8以上版本,然后需要准入控制中加入podpreset
我们经常有一个需求是同步pod和宿主机的时间,一般情况下,我们是通过挂载宿主机的localtime来完成的

[root@master1 ~]# cat time-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: time-demo
labels:
app: time
spec:
containers:
- name: time-demo
image: nginx
ports:
- containerPort: 80
我们可以看到pod的时间和nodes时间是不一样的,这时候我们可以挂载主机的localtime文件到pod中去
[root@master1 ~]# cat time-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: time-demo
labels:
app: time
spec:
volumes:
- name: host-time
hostPath:
path: /etc/localtime
containers:
- name: time-demo
image: nginx
volumeMounts:
- name: host-time
mountPath: /etc/localtime
ports:
- containerPort: 80
此时pod就和node的时间一样了。但是往往我们素有的pod都有时间同步的需要,如果所有pod都挂载太麻烦,这个时候可以使用PodPreset来预设模板
[root@master1 ~]# cat time-preset.yaml
apiVersion: settings.k8s.io/v1alpha1
kind: PodPreset
metadata:
name: time-preset
namespace: default
spec:
selector:
mathLables:
volumeMounts:
- name: localtime
mountPath: /etc/localtime
volumes:
- name: localtime
hostPath:
path: /etc/localtime
在此之前我们需要修改apiVersion的参数
/etc/kubernetes/manifests/kube-apiserver.yaml 修改完移动一下kube-apiversion.yaml文件,相当于强制启动
root@master1 ~]# cat /etc/kubernetes/manifests/kube-apiserver.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 192.168.1.126:6443
creationTimestamp: null
labels:
component: kube-apiserver
tier: control-plane
name: kube-apiserver
namespace: kube-system
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.1.126
- --allow-privileged=true
- --authorization-mode=Node,RBAC
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --enable-admission-plugins=NodeRestriction
- --enable-bootstrap-token-auth=true
- --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
- --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
- --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
- --etcd-servers=https://127.0.0.1:2379
- --insecure-port=0
- --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
- --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
- --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
- --requestheader-allowed-names=front-proxy-client
- --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
- --requestheader-extra-headers-prefix=X-Remote-Extra-
- --requestheader-group-headers=X-Remote-Group
- --requestheader-username-headers=X-Remote-User
- --secure-port=6443
- --service-account-key-file=/etc/kubernetes/pki/sa.pub
- --service-cluster-ip-range=10.96.0.0/12
- --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
- --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
- --enable-admission-plugins=NodeRestriction,PodPreset //新加的这两行
- --runtime-config=settings.k8s.io/v1alpha1=true // 新加的这两行
image: registry.aliyuncs.com/google_containers/kube-apiserver:v1.19.0
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 8
httpGet:
host: 192.168.1.126
path: /livez
port: 6443
scheme: HTTPS
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
name: kube-apiserver
readinessProbe:
failureThreshold: 3
httpGet:
host: 192.168.1.126
path: /readyz
port: 6443
scheme: HTTPS
periodSeconds: 1
timeoutSeconds: 15
resources:
requests:
cpu: 250m
startupProbe:
failureThreshold: 24
httpGet:
host: 192.168.1.126
path: /livez
port: 6443
scheme: HTTPS
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
volumeMounts:
- mountPath: /etc/ssl/certs
name: ca-certs
readOnly: true
- mountPath: /etc/pki
name: etc-pki
readOnly: true
- mountPath: /etc/kubernetes/pki
name: k8s-certs
readOnly: true
hostNetwork: true
priorityClassName: system-node-critical
volumes:
- hostPath:
path: /etc/ssl/certs
type: DirectoryOrCreate
name: ca-certs
- hostPath:
path: /etc/pki
type: DirectoryOrCreate
name: etc-pki
- hostPath:
path: /etc/kubernetes/pki
type: DirectoryOrCreate
name: k8s-certs
status: {}

这种就是开启的
验证一下pod的状态

kubectl get pods -l app=time 筛选一下podname

可以看到pod和node的时间是一致的
[root@master1 ~]# kubectl get pod time-demo -o yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"time"},"name":"time-demo","namespace":"default"},"spec":{"containers":[{"image":"nginx","name":"time-demo","ports":[{"containerPort":80}],"volumeMounts":[{"mountPath":"/etc/localtime","name":"host-time"}]}],"volumes":[{"hostPath":{"path":"/etc/localtime"},"name":"host-time"}]}}
creationTimestamp: "2022-04-28T09:19:55Z"
labels:
app: time
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:kubectl.kubernetes.io/last-applied-configuration: {}
f:labels:
.: {}
f:app: {}
f:spec:
f:containers:
k:{"name":"time-demo"}:
.: {}
f:image: {}
f:imagePullPolicy: {}
f:name: {}
f:ports:
.: {}
k:{"containerPort":80,"protocol":"TCP"}:
.: {}
f:containerPort: {}
f:protocol: {}
f:resources: {}
f:terminationMessagePath: {}
f:terminationMessagePolicy: {}
f:volumeMounts:
.: {}
k:{"mountPath":"/etc/localtime"}:
.: {}
f:mountPath: {}
f:name: {}
f:dnsPolicy: {}
f:enableServiceLinks: {}
f:restartPolicy: {}
f:schedulerName: {}
f:securityContext: {}
f:terminationGracePeriodSeconds: {}
f:volumes:
.: {}
k:{"name":"host-time"}:
.: {}
f:hostPath:
.: {}
f:path: {}
f:type: {}
f:name: {}
manager: kubectl-client-side-apply
operation: Update
time: "2022-04-28T09:19:55Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:status:
f:conditions:
k:{"type":"ContainersReady"}:
.: {}
f:lastProbeTime: {}
f:lastTransitionTime: {}
f:status: {}
f:type: {}
k:{"type":"Initialized"}:
.: {}
f:lastProbeTime: {}
f:lastTransitionTime: {}
f:status: {}
f:type: {}
k:{"type":"Ready"}:
.: {}
f:lastProbeTime: {}
f:lastTransitionTime: {}
f:status: {}
f:type: {}
f:containerStatuses: {}
f:hostIP: {}
f:phase: {}
f:podIP: {}
f:podIPs:
.: {}
k:{"ip":"10.244.1.43"}:
.: {}
f:ip: {}
f:startTime: {}
manager: kubelet
operation: Update
time: "2022-04-28T09:20:14Z"
name: time-demo
namespace: default
resourceVersion: "239546"
selfLink: /api/v1/namespaces/default/pods/time-demo
uid: c0f154d6-e20f-48b9-a787-bdaadcec6249
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: time-demo
ports:
- containerPort: 80
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /etc/localtime
name: host-time
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-sbhsk
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: node1
preemptionPolicy: PreemptLowerPriority
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- hostPath:
path: /etc/localtime
type: ""
name: host-time
- name: default-token-sbhsk
secret:
defaultMode: 420
secretName: default-token-sbhsk
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2022-04-28T09:19:55Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2022-04-28T09:20:14Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2022-04-28T09:20:14Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2022-04-28T09:19:55Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://c92926918312220c9dc2360244d8b72a1e3452c54f36179b775c8b46f6dab73f
image: nginx:latest
imageID: docker-pullable://nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
lastState: {}
name: time-demo
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2022-04-28T09:20:14Z"
hostIP: 192.168.1.127
phase: Running
podIP: 10.244.1.43
podIPs:
- ip: 10.244.1.43
qosClass: BestEffort
startTime: "2022-04-28T09:19:55Z"
本文详细介绍了Kubernetes的Downward API,包括如何通过环境变量和volume挂载将pod信息注入容器,以及如何获取pod的元数据如labels和annotations。此外,还提到了podpreset功能,用于自动填充pod字段,以及时间同步的方法。

810

被折叠的 条评论
为什么被折叠?



