对于某些需要调度之后才能知道的数据,比如 pod 的 ip,主机名,或者 pod 自身的名称等等,k8s 依旧很贴心的提供了 Downward API 的方式来获取此类数据,并且可以通过环境变量或者文件(downwardApi卷中)来传递 pod 的元数据。
可以传递的容器数据包括如下:
通过环境变量暴露元数据
创建一个但容器的 pod
$ vim ./dowanwardapi-learn.yaml
apiVersion: v1
kind: Pod
metadata:
name: downward-learn
spec:
containers:
name: main
image: busybox
command: ["sleep", "999999"]
resources:
requests:
cpu: "15m"
memory: "100Ki"
limits:
cpu: "100m"
memory: "4Mi"
env:
name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
name: CONTAINER_CPU_REQUEST_MILLICORES
valueFrom:
resourceFieldRef:
resource: requests.cpu
divisor: "1m"
name: CONTAINER_MEMORY_LIMIT_KIBIBYTES
valueFrom:
resourceFieldRef:
resource: limits.memory
divisor: "1Ki"
创建完成后我们可以使用 kubectl exec 命令来查看容器中的所有环境变量,如下:
$ kubectl exec downward-learn env
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=downward-learn
POD_NAME=downward-learn
POD_IP=10.44.0.3
NODE_NAME=node1
CONTAINER_CPU_REQUEST_MILLICORES=15
CONTAINER_MEMORY_LIMIT_KIBIBYTES=4096
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
HOME=/root
但是有一些变量并不能根据环境变量暴露,比如 lables 标签和 annotations 注释等等,但是这些可以使用过 dowanwardApi 卷的方式来进行载入。
通过 downwardAPI 卷来传递元数据
和环境变量一样,通过文件卷的方式也需要显式指定元数据字段来暴露给进程,如下:
apiVersion: v1
kind: Pod
metadata:
name: downward-learn
spec:
containers:
name: main
image: busybox
command: ["sleep", "999999"]
resources:
requests:
cpu: "15m"
memory: "100Ki"
limits:
cpu: "100m"
memory: "4Mi"
volumeMounts:
name: downward
downwardAPI:
iterms:
path: "podName"
fileRef:
fieldPath: metadata.name
……
其中声明元数据和配置的方式没什么不同。
但是其中需要注意的是,如果是暴露容器级的元数据时,比如容器可使用的资源限制和资源请求(如使用字段 resourceFieldRef),必须指定引入资源字段的容器名称,比如:
spec:
volumes:
name: downward
downwardAPI:
items:
path: "containerCpuRequestMilliCores"
resourceFieldRef:
containerName: main ## 容器名称
resource: requests.cpu
divisor: 1m
这里由于引入了cpu资源限制,所以也贴一下所用到的,在 pod 内查询当前的 cpu 使用进程代码,因为 pod 容器内的查询 cpu 使用和物理机上的还不太一样,在网上找了一些但是都不太适合容器使用,所以自己写了一个
$ vim cpu.go
package handler
import (
"fmt"
"os"
linuxproc "github.com/c9s/goprocinfo/linux"
)
var (
prevUsageUser int64 = 0
prevUsageSystem int64 = 0
cpuNum = 1 // 设置该容器内使用的cpu个数
)
func GetCpuCount(stat *linuxproc.Stat) (count float64) {
cfsQuota := getCgoupValueByPath("/sys/fs/cgroup/cpu/cpu.cfs_quota_us")
cfsPeriod := getCgoupValueByPath("/sys/fs/cgroup/cpu/cpu.cfs_period_us")
if cfsQuota == -1 {
return float64(len(stat.CPUStats))
}
return float64(cfsQuota) / float64(cfsPeriod)
}
func CpuCountToString(c float64) string {
if c == float64(int64(c)) {
return fmt.Sprintf("%v", c)
}
return fmt.Sprintf("%0.1f", c)
}
// GetCpuUsage should be called every 1 seconds. not quite precise.
func GetCpuUsage(cpus float64) (user, system, idle float64) {
var currentUsageUser, currentUsageSystem int64
currentUsageUser = getCgoupValueByPath("/sys/fs/cgroup/cpuacct/cpuacct.usage_user")
currentUsageSystem = getCgoupValueByPath("/sys/fs/cgroup/cpuacct/cpuacct.usage_sys")
if prevUsageUser == 0 && prevUsageSystem == 0 {
prevUsageUser = currentUsageUser
prevUsageSystem = currentUsageSystem
return
}
user = float64(currentUsageUser-prevUsageUser) / 10000000 / cpus // / 1000,000,000 \* 100 = /10,000,000
system = float64(currentUsageSystem-prevUsageSystem) / 10000000 / cpus // / 1000,000,000 \* 100 = /10,000,000
idle = 100 - user - system
if idle < 0 {
idle = 0
}
prevUsageUser = currentUsageUser
prevUsageSystem = currentUsageSystem
return
}
func getCgoupValueByPath(path string) int64 {
data, err := os.ReadFile(path)
if err != nil {
return 0
}
var value int64
n, err := fmt.Sscanf(string(data), "%d", &value)
if err != nil || n != 1 {
return 0
}
return value
}
计算出来当前的容器数值换算为:use 80% = 800
这样在容器内就能根据元数据和监控脚本时刻监控容器的 cpu 使用率了。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章