通过设置 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 <map[string]string>
# 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 <your-node-name> 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