一.初始化容器initContainer
参考链接:https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/init-containers/
应用场景:1.创建文件;2.修改内核参数;3.等待依赖程序启动等
1. 示例1:等待依赖服务启动
后端应用需要依赖数据库服务
initContainers:
- command:
- sh
- -c
- for i in {1..100}; do sleep 1; echo $i; if dig SERVICE_NAME_OR_DOMAIN; then exit 0; fi; exit 1; done
env:
- name: TZ
value: Aisa/Shanghai
- name: LANG
value: C.UTF-8
image: centos:6
imagePullPolicy: Always
name: check-service
restartPolicy: Always
2. 示例2:服务注册
注册这个Pod的IP到远程服务器,通过在命令中调用API
initContainers:
- command:
- sh
- -c
- |
curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register \
-d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
env:
- name: TZ
value: Aisa/Shanghai
- name: LANG
value: C.UTF-8
image: curl
imagePullPolicy: Always
name: init-curl
restartPolicy: Always
3. 示例3:克隆Git代码到容器中
initContainers:
- command:
- sh
- -c
- |
git clone https://github.com/dotbalo/kubernetes-guide.git
env:
- name: TZ
value: Aisa/Shanghai
- name: LANG
value: C.UTF-8
image: alpine/git:latest
imagePullPolicy: Always
name: init-git
restartPolicy: Always
4. 示例4:多个初始化容器使用
一个应用需要等待该应用所在Namespace的一个Service对应的Pod启动,也需要一个DB的Service启动。
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
# 业务应用容器
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
# 初始化容器列表
initContainers:
# 第1个初始化容器,等待当前ns下的myservice启动
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
# 第2个初始化容器,等待DB的service启动
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
# 查看容器日志
k logs myapp-pod -c init-myservice
k logs myapp-pod -c init-mydb
二.临时容器——Ephemeral Containers
参考链接:[https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/ephemeral-containers/](https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/ephemeral-containers/)
用来调试程序,不会影响正常容器。
在1.18+版本使用的步骤:
k alpha debug(1.18版)
k debug(1.19版+)
k debug metrics-server-795dc6d4d8-mzcjl -i --image=busybox -n kube-system
三.HPA——自动扩缩容
参考链接:https://kubernetes.io/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/
前提:需要依赖metrics server,不适用于无法缩放的对象如daemonset
实践:
# 新建deploy
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-server
name: nginx-server
spec:
replicas: 1
selector:
matchLabels:
app: nginx-server
template:
metadata:
labels:
app: nginx-server
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
resources:
limits:
cpu: 100m
# clusterIP
k expose deploy nginx-server --port=80
# 新建HPA,平均cpu利用率是10%,允许最大的Pod数量为10,最少为1
k autoscale deploy nginx-server --cpu-percent=10 --min=1 --max=10
# 当前HPA状态,未发送请求,CPU使用率为10%
k get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-server Deployment/nginx-server 0%/10% 1 10 6 3m48s
k get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-server ClusterIP 10.96.161.205 <none> 80/TCP 2m10s
# 模拟访问
while true;do curl 10.96.161.205 &> /dev/null; done
# CPU升高
k get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-server Deployment/nginx-server 40%/10% 1 10 6 2m36s
# Pod自动扩容
k get pods
NAME READY STATUS RESTARTS AGE
nginx-server-74544d6d5f-dfbmp 0/1 Pending 0 46s
nginx-server-74544d6d5f-dkf85 0/1 Pending 0 61s
nginx-server-74544d6d5f-dqg45 1/1 Running 0 3m36s
nginx-server-74544d6d5f-gkdt5 0/1 Pending 0 46s
nginx-server-74544d6d5f-wvgbc 0/1 Pending 0 61s
nginx-server-74544d6d5f-xskn6 0/1 Pending 0 61s
四.Taints和Toleration
参考链接:https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/taint-and-toleration/
添加污点:
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule
如果给一个节点添加了一个 effect 值为 NoExecute的污点, 则任何不能忍受这个污点的 Pod 都会马上被驱逐,任何可以忍受这个污点的 Pod 都不会被驱逐。
删除污点:
kubectl taint nodes node1 key1:NoSchedule-
查看污点:
kubectl describe node node1|grep Taints
五.Affinity亲和力——只有在调度时起作用
参考链接:https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity
亲和力分为软亲和力(非强制性) preferredDuringSchedulingIgnoredDuringExecution和硬亲和力(强制性)requiredDuringSchedulingIgnoredDuringExecution
- 1.Node Affinity:根据节点的标签进行匹配。
- 2.PodAffinity(Pod亲和力):根据Pod的标签进行匹配。
- 3.PodAntiAffinity(Pod反亲和力)
1.Node Affinity
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k8s-master-node1
- k8s-worker-node1
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1 # 权重越高优先级越大
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: nginx
imagePullPolicy: IfNotPresent
只能部署在具有label的key为kubernetes.io/hostname,value为k8s-master-node1或k8s-worker-node1的节点上(硬亲和力),在满足条件后,尽量部署在具有another-node-label-key=another-node-label-value的节点(软亲和力),没有该标签的node不会影响部署。
2.PodAffinity和PodAntiAffinity
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: failure-domain.beta.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: failure-domain.beta.kubernetes.io/zone
containers:
- name: with-pod-affinity
image: nginx
必须和具有security=S1标签的Pod部署在同一域内,域的名称是failure-domain.beta.kubernetes.io/zone;尽量不和具有security=S2标签的Pod部署在同一域内。
Pod的标签是Pod本身的配置,所以和Pod一样具有隔离性,在配置Pod亲和力和反亲和力时可以匹配其他Namespace下Pod的标签。指定和kube-public ns具有security为S1标签的Pod部署在同一个域的配置如下:
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
namespaces:
- kube-public
topologyKey: failure-domain.beta.kubernetes.io/zone
示例1:同一应用部署在不同宿主机
将一个应用部署在不同的节点上,达到更高的可用率,以免同一个应用部署到相同的宿主机带来风险。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: must-be-diff-nodes
name: must-be-diff-nodes
namespace: kube-public
spec:
replicas: 3
selector:
matchLabels:
app: must-be-diff-nodes
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
labels:
app: must-be-diff-nodes
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- must-be-diff-nodes
topologyKey: "kubernetes.io/hostname"
containers:
- name: must-be-diff-nodes
image: nginx
imagePullPolicy: Always
env:
- name: TZ
value: Asia/Shanghai
- name: LANG
value: C.UTF-8
示例2:同一应用不同副本的固定节点
适用于有状态服务,NodeSelector/NodeAffinity+PodAntiAffinity
部署2个redis示例,部署至2台宿主机,且单个实例部署的节点保持不变
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-cache
spec:
selector:
matchLabels:
app: store
replicas: 2
template:
metadata:
labels:
app: store
spec:
nodeSelector:
app: store
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: redis-server
image: redis:3.2-alpine
示例3:应用和缓存尽量部署在同一域内
后端应用请求数据库服务会增大数据库服务的压力,直接请求缓存中间件可以提高数据加载速度,减少网络消耗。
部署2个不在同一域内的nginx实例,但必须和redis在同一域内。
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
selector:
matchLabels:
app: web-store
replicas: 2
template:
metadata:
labels:
app: web-store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-store
topologyKey: "kubernetes.io/hostname"
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: web-app
image: nginx:1.16-alpine