
《重识云原生系列》专题索引:
通过设置 dnsPolicy 参数,设置 Pod 中容器访问 DNS 的策略:
通过设置 spec.hostIPC 参数为 true,使用主机的 IPC 命名空间,默认为 false。
通过设置 spec.hostNetwork 参数为 true,使用主机的网络命名空间,默认为 false。
通过设置 spec.hostPID 参数为 true,使用主机的 PID 命名空间,默认为 false。
- apiVersion: v1
- kind: Pod
- metadata:
- name: busybox1
- labels:
- name: busybox
- spec:
- hostIPC: true
- hostPID: true
- hostNetwork: true
- containers:
- - image: busybox
- command:
- - sleep
- - "3600"
- name: busybox
通过 spec.hostname 参数实现,如果未设置默认使用 metadata.name 参数的值作为 Pod 的 hostname。
通过 spec.subdomain 参数设置 Pod 的子域名,默认为空。比如,指定 hostname 为 busybox-2 和 subdomain 为 default-subdomain,完整域名为 busybox-2.default-subdomain.default.svc.cluster.local,也可以简写为 busybox-2.default-subdomain.default:
- apiVersion: v1
- kind: Pod
- metadata:
- name: busybox2
- labels:
- name: busybox
- spec:
- hostname: busybox-2
- subdomain: default-subdomain
- containers:
- - image: busybox
- command:
- - sleep
- - "3600"
- name: busybox
注意:
- kind: Service
- apiVersion: v1
- metadata:
- name: default-subdomain
- spec:
- clusterIP: None
- selector:
- name: busybox
- ports:
- - name: foo
- # Actually, no port is needed.
- port: 1234
- targetPort: 1234
注意:
必须为 headless service 设置至少一个服务端口(spec.ports,即便它看起来并不需要),否则 Pod 与 Pod 之间依然无法通过完整域名来访问。
从 v1.9 开始,可以在 kubelet 和 kube-apiserver 中设置 --feature-gates=CustomPodDNS=true 开启设置每个 Pod DNS 地址的功能。
注意:该功能在 v1.10 中为 Beta 版,v1.9 中为 Alpha 版。
- apiVersion: v1
- kind: Pod
- metadata:
- namespace: default
- name: dns-example
- spec:
- containers:
- - name: test
- image: nginx
- dnsPolicy: "None"
- dnsConfig:
- nameservers:
- - 1.2.3.4
- searches:
- - ns1.svc.cluster.local
- - my.dns.search.suffix
- options:
- - name: ndots
- value: "2"
- - name: edns0
对于旧版本的集群,可以使用 ConfigMap 来自定义 Pod 的 /etc/resolv.conf,如:
- kind: ConfigMap
- apiVersion: v1
- metadata:
- name: resolvconf
- namespace: default
- data:
- resolv.conf: |
- search default.svc.cluster.local svc.cluster.local cluster.local
- nameserver 10.0.0.10
-
- ---
- kind: Deployment
- apiVersion: extensions/v1beta1
- metadata:
- name: dns-test
- namespace: default
- spec:
- replicas: 1
- template:
- metadata:
- labels:
- name: dns-test
- spec:
- containers:
- - name: dns-test
- image: alpine
- stdin: true
- tty: true
- command: ["sh"]
- volumeMounts:
- - name: resolv-conf
- mountPath: /etc/resolv.conf
- subPath: resolv.conf
- volumes:
- - name: resolv-conf
- configMap:
- name: resolvconf
- items:
- - key: resolv.conf
- path: resolv.conf
Kubernetes 通过 cgroups 限制容器的 CPU 和内存等计算资源,包括 requests(请求,调度器保证调度到资源充足的 Node 上,如果无法满足会调度失败)和 limits(上限)等:
比如 nginx 容器请求 30% 的 CPU 和 56MB 的内存,但限制最多只用 50% 的 CPU 和 128MB 的内存:
- apiVersion: v1
- kind: Pod
- metadata:
- labels:
- app: nginx
- name: nginx
- spec:
- containers:
- - image: nginx
- name: nginx
- resources:
- requests:
- cpu: "300m"
- memory: "56Mi"
- limits:
- cpu: "1"
- memory: "128Mi"
注意
#查看livenessProbe帮助命令:
kubectl explain pods.spec.containers.livenessProbe
#查看readinessProbe帮助命令:
kubectl explain pods.spec.containers.readinessProbe
整个图如下:

从上面可以看出,我们pod在从创建到结束之前,会一直处于某种状态之中。
- [root@master yaml]# cat liveness.yaml
- kind: Pod
- apiVersion: v1
- metadata:
- name: liveness
- labels:
- test: liveness
- spec:
- restartPolicy: OnFailure
- containers:
- - name: liveness
- image: busybox
- args:
- - /bin/sh
- - -c
- - touch /tmp/test; sleep 60; rm -rf /tmp/test; sleep 300
- livenessProbe:
- exec:
- command:
- - cat
- - /tmp/test
- initialDelaySeconds: 10
- periodSeconds: 5
上述yaml文件中针对/tmp/test这个文件进行指定了健康检查策略为 livenessProbe,并且指定了重启策略为OnFailure。这样容器可以正常的运行,但是总是会重启。如图:

配置几乎是一模一样的,只是健康检测的方式更换一下,如下:
- [root@master yaml]# cat readiness.yaml
- kind: Pod
- apiVersion: v1
- metadata:
- name: readiness
- labels:
- test: readiness
- spec:
- restartPolicy: OnFailure
- containers:
- - name: readiness
- image: busybox
- args:
- - /bin/sh
- - -c
- - touch /tmp/test; sleep 60; rm -rf /tmp/test; sleep 300
- readinessProbe:
- exec:
- command:
- - cat
- - /tmp/test
- initialDelaySeconds: 10
- periodSeconds: 5
那么此时运行的pod状态如图:

查看的效果可能不是很明显,使用以下方法,便可查看具体的效果。
- [root@master yaml]# cat hcscal.yaml
- kind: Deployment
- apiVersion: extensions/v1beta1
- metadata:
- name: web
- spec:
- replicas: 3
- template:
- metadata:
- labels:
- run: web
- spec:
- containers:
- - name: web
- image: httpd
- ports:
- - containerPort: 80
- readinessProbe:
- httpGet:
- scheme: HTTP
- path: /healthy
- port: 80
- initialDelaySeconds: 10
- periodSeconds: 5
-
- ---
-
- kind: Service
- apiVersion: v1
- metadata:
- name: web-svc
- spec:
- type: NodePort
- selector:
- run: web
- ports:
- - protocol: TCP
- port: 90
- targetPort: 80
- nodePort: 30321
创建一个deployment资源、一个Service资源并且相互之间进行关联。
执行的结果如图:

由此可以得出以下结论:
每种探针都支持以下三种探测方式:
主要应用是在scale(扩容、缩容)、更新(升级)过程中使用。下面通过一个简单的小实验进行验证:
- [root@master yaml]# cat app.v1.yaml
- //版本1的yaml文件创建10个副本使用busybox镜像,如下:
- apiVersion: extensions/v1beta1
- kind: Deployment
- metadata:
- name: app
- spec:
- replicas: 10
- template:
- metadata:
- labels:
- run: app
- spec:
- containers:
- - name: app
- image: busybox
- args:
- - /bin/sh
- - -c
- - sleep 10; touch /tmp/healthy; sleep 3000
- readinessProbe:
- exec:
- command:
- - cat
- - /tmp/healthy
- initialDelaySeconds: 10
- periodSeconds: 5
使用yaml文件生成相应的资源,并且记录历史版本信息:
[root@master yaml]# kubectl apply -f app.v1.yaml --record
查看pod信息,如图:

- [root@master yaml]# cat app.v2.yaml
- //版本2的yaml文件创建10个副本使用busybox镜像
- //并模拟(代码中有问题,并进行升级),如下:
- apiVersion: extensions/v1beta1
- kind: Deployment
- metadata:
- name: app
- spec:
- strategy:
- rollingUpdate:
- maxSurge: 2
- maxUnavailable: 2
- replicas: 10
- template:
- metadata:
- labels:
- run: app
- spec:
- containers:
- - name: app
- image: busybox
- args:
- - /bin/sh
- - -c
- - sleep 3000
- readinessProbe:
- exec:
- command:
- - cat
- - /tmp/healthy
- initialDelaySeconds: 10
- periodSeconds: 5
- //maxSurge:此参数控制滚动更新过程中,副本总数超过预期数的值,可以是整数,也可以是百分比。默认是1
- //maxUnavailable:不可用Pod的值,默认为1,可以是整数,也可以是百分比
-
- [root@master yaml]# kubectl apply -f app.v2.yamll --record
查看pod信息,如图:

从图中可以看出,一共有12个pod,并且有四个pod是不可用的!因为健康检查机制在检查到有问题时,就不会更新了剩余的pod了!
- [root@master yaml]# cat app.v3.yaml
- //版本2的yaml文件创建10个副本使用busybox镜像
- //并且不使用健康检查机制,如下:
- apiVersion: extensions/v1beta1
- kind: Deployment
- metadata:
- name: app
- spec:
- replicas: 10
- template:
- metadata:
- labels:
- run: app
- spec:
- containers:
- - name: app
- image: busybox
- args:
- - /bin/sh
- - -c
- - sleep 3000
-
- [root@master yaml]# kubectl apply -f app.v3.yamll --record
再次查看pod的状态信息,如图:

如果不使用健康检查机制,就可以看出及时pod中服务存在问题,也会全部更新!
- [root@master yaml]# kubectl rollout history deployment app //查看记录的历史版本
- [root@master yaml]# kubectl rollout undo deployment app --to-revision=1 //回滚到可用的版本
再次查看pod的运行状态,如图:

由此可以看出pod健康检查的重要性!
namespace叫做命名空间,可以把k8s集群划分成多个名称空间,然后对不同的名称空间的资源做隔离,可以控制各个名称空间的入栈,出栈策略,是一种在多个用户之间划分群集资源的方法。
#查看k8s集群当前有哪些名称空间:
kubectl get namespace
(1)什么是标签?
标签其实就一对 key/value ,被关联到对象上,比如Pod,标签的使用我们倾向于能够标示对象的特殊特点,并且对用户而言是有意义的(就是一眼就看出了这个Pod是干什么的),标签可以用来划分特定组的对象(比如版本,服务类型等),标签可以在创建一个对象的时候直接给与,也可以在后期随时修改,每一个对象可以拥有多个标签,但是,key值必须是唯一的。
(2)查看所有pod资源对象的标签
kubectl get pods --show-labels
(3)查看带有指定标签的pod
kubectl get pods -L web1
(4)显示所有资源对象下web1这个标签的标签值
kubectl get pods -l web1 --show-labels
查看拥有web1这个标签的资源对象,并且把标签显示出来。
(5)想修改资源的标签,比方说想给web加上个release标签
给资源对象打标签要使用label命令,指定给某个类型下的某个资源打标签,资源中的key/value可以是多个,因此在web(pod名字)这个资源下再打个标签release,用如下命令:
kubectl label pods web release=new
查看标签是否打成功:
kubectl get pods --show-labels
显示如下,显示如下,说明标签达成功了;
- NAME READY STATUS RESTARTS AGE LABELS
- web 1/1 Running 1 21h release=new,web1=tomcat
(6)k8s的标签选择器:
与name和UID不同,label不提供唯一性。通常,我们会看到很多对象有着一样的label。通过标签选择器,客户端/用户能方便辨识出一组对象。
API目前支持两种标签选择器:
一个label选择器可以由多个必须条件组成,由逗号分隔。在多个必须条件指定的情况下,所有的条件都必须满足,因而逗号起着AND逻辑运算符的作用。
一个空的label选择器(即有0个必须条件的选择器)会选择集合中的每一个对象。
一个null型label选择器(仅对于可选的选择器字段才可能)不会返回任何对象。
基于等值关系的标签选择器:=,==,!=
基于相等性或者不相等性的条件允许用label的键或者值进行过滤。匹配的对象必须满足所有指定的label约束,尽管他们可能也有额外的label。有三种运算符是允许的,“=”,“==”和“!=”。前两种代表相等性(他们是同义运算符),后一种代表非相等性。例如:
environment = production tier != frontend
第一个选择所有键等于 environment 值为 production 的资源。后一种选择所有键为 tier 值不等于 frontend 的资源,和那些没有键为 tier 的label的资源。
要过滤所有处于 production 但不是 frontend 的资源,可以使用逗号操作符,
environment=production,tier!=frontend
基于集合的标签选择器:
基于集合的label条件允许用一组值来过滤键。支持三种操作符: in , notin ,和 exists(仅针对于key符号) 。例如:
- environment in (production, qa)
-
- tier notin (frontend, backend)
第一个例子,选择所有键等于 environment ,且value等于 production 或者 qa 的资源。 第二个例子,选择所有键等于tier且值是除了frontend 和 backend 之外的资源,和那些没有label的键是 tier 的资源。 类似的,逗号操作符相当于一个AND操作符。因而要使用一个 partition 键(不管值是什么),并且 environment 不是 qa 过滤资源可以用 partition,environment notin (qa) 。
基于集合的选择器是一个相等性的宽泛的形式,因为 environment=production 相当于environment in (production) ,与 != and notin 类似。
基于集合的条件可以与基于相等性 的条件混合。例如, partition in (customerA,customerB),environment != qa 。
标签选择器根据定义的标签可以选择匹配到的资源对象。
更多详细信息可参考:
Labels and Selectors | Kubernetes
node label
(1)查看nodes节点的标签
kubectl get nodes --show-labels
(2)给node节点打标签:
kubectl label nodes node1 node011=haha kubectl get nodes --show-labels
可以看到node01上有node011这个标签了。
(3)节点选择器nodeSelector
- #查看nodeSelector帮助命令
- kubectl explain pods.spec.nodeSelector
-
- # nodeSelector
- # NodeSelector is a selector which must be true for the pod to fit on a node.
- # Selector which must match a node's labels for the pod to be scheduled on that node.
- # More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
上面有一个nodeSelector,这个是节点标签选择器,可以限制pod运行在哪个节点上
kubectl get pods -o wide
从上面可以看到web运行在node1上,如果我们想要让它运行在master1上,就需要用到节点选择器:
- nodeSelector:
-
- node011: haha #这个node011是我们给node1节点打的标签,在上面已经操作过
cat pod.yaml 看到完整的文件如下:
- apiVersion: v1
- kind: Pod
- metadata:
- name: web
- namespace: default
- labels:
- web1: tomcat
- spec:
- containers:
- - name: tomcat1
- image: tomcat:8.5-jre8-alpine
- nodeSelector:
- node011:haha
-
- kubectl delete -f pod.yaml
- kubectl apply -f pod.yaml
- kubectl get pods -o wide
显示pod运行在node1上。
如果node1和node2都有node011这个标签,那么nodeSelector则根据调度策略调度pod到相应的node节点上。
更多详细信息可参考:
Assigning Pods to Nodes | Kubernetes
节点名称
nodeName:指定pod节点运行在哪个具体node上,不存在调度说法。
查看 nodeName帮助命令:
kubectl explain pods.spec.nodeName
默认情况下,容器都是以非特权容器的方式运行。比如,不能在容器中创建虚拟网卡、配置虚拟网络。
Kubernetes 提供了修改 Capabilities 的机制,可以按需要给容器增加或删除。比如下面的配置给容器增加了 CAP_NET_ADMIN 并删除了 CAP_KILL。
- apiVersion: v1
- kind: Pod
- metadata:
- name: cap-pod
- spec:
- containers:
- - name: friendly-container
- image: "alpine:3.4"
- command: ["/bin/sleep", "3600"]
- securityContext:
- capabilities:
- add:
- - NET_ADMIN
- drop:
- - KILL
可以通过给 Pod 增加 kubernetes.io/ingress-bandwidth 和 kubernetes.io/egress-bandwidth 这两个 annotation 来限制 Pod 的网络带宽:
- apiVersion: v1
- kind: Pod
- metadata:
- name: qos
- annotations:
- kubernetes.io/ingress-bandwidth: 3M
- kubernetes.io/egress-bandwidth: 4M
- spec:
- containers:
- - name: iperf3
- image: networkstatic/iperf3
- command:
- - iperf3
- - -s
仅 kubenet 支持限制带宽目前只有 kubenet 网络插件支持限制网络带宽,其他 CNI 网络插件暂不支持这个功能。
kubenet 的网络带宽限制其实是通过 tc 来实现的:
- # setup qdisc (only once)
- tc qdisc add dev cbr0 root handle 1: htb default 30
- # download rate
- tc class add dev cbr0 parent 1: classid 1:2 htb rate 3Mbit
- tc filter add dev cbr0 protocol ip parent 1:0 prio 1 u32 match ip dst 10.1.0.3/32 flowid 1:2
- # upload rate
- tc class add dev cbr0 parent 1: classid 1:3 htb rate 4Mbit
- tc filter add dev cbr0 protocol ip parent 1:0 prio 1 u32 match ip src 10.1.0.3/32 flowid 1:3
可以通过 nodeSelector、nodeAffinity、podAffinity 以及 Taints 和 tolerations 等来将 Pod 调度到需要的 Node 上。
也可以通过设置 nodeName 参数,将 Pod 调度到指定 node 节点上。
比如,使用 nodeSelector,首先给 Node 加上标签:
kubectl label nodes disktype=ssd
接着,指定该 Pod 只想运行在带有 disktype=ssd 标签的 Node 上:
- apiVersion: v1
- kind: Pod
- metadata:
- name: nginx
- labels:
- env: test
- spec:
- containers:
- - name: nginx
- image: nginx
- imagePullPolicy: IfNotPresent
- nodeSelector:
- disktype: ssd
nodeAffinity、podAffinity 以及 Taints 和 tolerations 等的使用方法请参考 调度器章节。
默认情况下,容器的 /etc/hosts 是 kubelet 自动生成的,并且仅包含 localhost 和 podName 等。不建议在容器内直接修改 /etc/hosts 文件,因为在 Pod 启动或重启时会被覆盖。
默认的 /etc/hosts 文件格式如下,其中 nginx-4217019353-fb2c5 是 podName:
- $ kubectl exec nginx-4217019353-fb2c5 -- cat /etc/hosts
- # Kubernetes-managed hosts file.
- 127.0.0.1 localhost
- ::1 localhost ip6-localhost ip6-loopback
- fe00::0 ip6-localnet
- fe00::0 ip6-mcastprefix
- fe00::1 ip6-allnodes
- fe00::2 ip6-allrouters
- 10.244.1.4 nginx-4217019353-fb2c5
从 v1.7 开始,可以通过 pod.Spec.HostAliases 来增加 hosts 内容,如:
- apiVersion: v1
- kind: Pod
- metadata:
- name: hostaliases-pod
- spec:
- hostAliases:
- - ip: "127.0.0.1"
- hostnames:
- - "foo.local"
- - "bar.local"
- - ip: "10.1.2.3"
- hostnames:
- - "foo.remote"
- - "bar.remote"
- containers:
- - name: cat-hosts
- image: busybox
- command:
- - cat
- args:
- - "/etc/hosts"
- $ kubectl logs hostaliases-pod
- # Kubernetes-managed hosts file.
- 127.0.0.1 localhost
- ::1 localhost ip6-localhost ip6-loopback
- fe00::0 ip6-localnet
- fe00::0 ip6-mcastprefix
- fe00::1 ip6-allnodes
- fe00::2 ip6-allrouters
- 10.244.1.5 hostaliases-pod
- 127.0.0.1 foo.local
- 127.0.0.1 bar.local
- 10.1.2.3 foo.remote
- 10.1.2.3 bar.remote
v1.8 + 支持给容器分配 HugePages,资源格式为 hugepages-(如 hugepages-2Mi)。使用前要配置:
使用示例
- apiVersion: v1
- kind: Pod
- metadata:
- generateName: hugepages-volume-
- spec:
- containers:
- - image: fedora:latest
- command:
- - sleep
- - inf
- name: example
- volumeMounts:
- - mountPath: /hugepages
- name: hugepage
- resources:
- limits:
- hugepages-2Mi: 100Mi
- volumes:
- - name: hugepage
- emptyDir:
- medium: HugePages
注意事项:
从 v1.8 开始,可以为 Pod 设置一个优先级,保证高优先级的 Pod 优先调度。
优先级调度功能目前为 Beta 版,在 v1.11 版本中默认开启。对 v1.8-1.10 版本中使用前需要开启:
为 Pod 设置优先级前,先创建一个 PriorityClass,并设置优先级(数值越大优先级越高):
- apiVersion: scheduling.k8s.io/v1alpha1
- kind: PriorityClass
- metadata:
- name: high-priority
- value: 1000000
- globalDefault: false
- description: "This priority class should be used for XYZ service pods only."
Kubernetes 自动创建了 system-cluster-critical 和 system-node-critical 等两个 PriorityClass,用于 Kubernetes 核心组件。
为 Pod 指定优先级:
- apiVersion: v1
- kind: Pod
- metadata:
- name: nginx
- labels:
- env: test
- spec:
- containers:
- - name: nginx
- image: nginx
- imagePullPolicy: IfNotPresent
- priorityClassName: high-priority
当调度队列有多个 Pod 需要调度时,优先调度高优先级的 Pod。而当高优先级的 Pod 无法调度时,Kubernetes 会尝试先删除低优先级的 Pod 再将其调度到对应 Node 上(Preemption)。
注意:受限于 Kubernetes 的调度策略,抢占并不总是成功。
PodDisruptionBudget (PDB) 用来保证一组 Pod 同时运行的数量,这些 Pod 需要使用 Deployment、ReplicationController、ReplicaSet 或者 StatefulSet 管理。
- apiVersion: policy/v1beta1
- kind: PodDisruptionBudget
- metadata:
- name: zk-pdb
- spec:
- maxUnavailable: 1
- selector:
- matchLabels:
- app: zookeeper
Sysctls 允许容器设置内核参数,分为安全 Sysctls 和非安全 Sysctls:
v1.6-v1.10 示例:
- apiVersion: v1
- kind: Pod
- metadata:
- name: sysctl-example
- annotations:
- security.alpha.kubernetes.io/sysctls: kernel.shm_rmid_forced=1
- security.alpha.kubernetes.io/unsafe-sysctls: net.ipv4.route.min_pmtu=1000,kernel.msgmax=1 2 3
- spec:
- ...
从 v1.11 开始,Sysctls 升级为 Beta 版本,不再区分安全和非安全 sysctl,统一通过 podSpec.securityContext.sysctls 设置,如:
- apiVersion: v1
- kind: Pod
- metadata:
- name: sysctl-example
- spec:
- securityContext:
- sysctls:
- - name: kernel.shm_rmid_forced
- value: "0"
- - name: net.ipv4.route.min_pmtu
- value: "552"
- - name: kernel.msgmax
- value: "65536"
- ...
很多容器都是配置了 UTC 时区,与国内集群的 Node 所在时区有可能不一致,可以通过 HostPath 存储插件给容器配置与 Node 一样的时区:
- apiVersion: v1
- kind: Pod
- metadata:
- name: sh
- namespace: default
- spec:
- containers:
- - image: alpine
- stdin: true
- tty: true
- volumeMounts:
- - mountPath: /etc/localtime
- name: time
- readOnly: true
- volumes:
- - hostPath:
- path: /etc/localtime
- type: ""
- name: time
Kubernetes中pod详解_人间不值得-的博客-CSDN博客
k8s之pod与Pod控制器 - woaiyitiaochai - 博客园
kubernetes 实践四:Pod详解 - xingyys - 博客园
K8S Pod详解_ldd儆儆的博客-CSDN博客_k8s pod
k8s之pod详解_爱show的小卤蛋的博客-CSDN博客_k8s pod