Usando
um serviço principal no negócio de segundo plano e cenário, várias réplicas foram configuradas. Como resultado, durante a implantação, descobriu-se que várias réplicas idênticas foram implantadas no mesmo host ao mesmo tempo. Quando o host falhou, todas as réplicas oscilaram em ao mesmo tempo, fazendo com que o serviço seja interrompido intermitentemente
Com base no histórico acima, várias cópias de um serviço são distribuídas para hosts diferentes, de modo que cada host tenha e possa executar apenas uma cópia do serviço.O atributo anti-afinidade do pod é usado aqui, ou seja, anti-afinidade do pod. A característica é que com base no rótulo do pod já em execução no nó, os pods com o mesmo rótulo não são mais agendados para o nó, de modo que apenas uma cópia do pod é executada em cada nó.
A diferença entre afinidade e antiafinidade do pod.
Afinidade (podAffinity): implantar no mesmo nó que o pod com o rótulo especificado.
Antiafinidade (podAntiAffinity): não deseja implantar o serviço no mesmo nó que o pod com o rótulo especificado.
podAntiAffinity Implantação real
A anti-afinidade é dividida em requisitos flexíveis e requisitos rígidos
requireDuringSchedulingIgnoredDuringExecution: Os requisitos rígidos devem atender às condições para garantir o efeito da implantação distribuída. Este método é melhor usado
preferidoDuringSchedulingIgnoredDuringExecution: Os requisitos flexíveis podem não ser totalmente atendidos, isso isto é, pode estar no mesmo nó. Pode executar várias cópias
# 配置如下,只需要修改label的配置,即matchExpressions中的key和values的值
# 硬性要求
# 如果节点上的pod标签存在满足app=nginx,则不能部署到节点上
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: "kubernetes.io/hostname"
# 软性要求
# 如果节点上的pod标签存在满足app=nginx,也可以部署到节点上,尽可能先部署到其它节点,如果没有满足也可以部署到此节点(大概是这么理解吧)
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: "kubernetes.io/hostname"
Em anexo está a configuração completa do deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 3
strategy:
rollingUpdate:
maxSurge: 30%
maxUnavailable: 0
type: RollingUpdate
minReadySeconds: 10
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: "kubernetes.io/hostname"
restartPolicy: "Always"
containers:
- name: nginx
image: nginx
imagePullPolicy: "IfNotPresent"
ports:
- containerPort: 80
name: http
protocol: TCP
Antiafinidade de pod para ambientes de produção reais
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
# Never schedule multiple replicas on the same node
- topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app.kubernetes.io/name: ${service}
app.kubernetes.io/instance: ${service}
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${service}
labels:
app.kubernetes.io/name: ${service}
app.kubernetes.io/version: 0.0.0
app.kubernetes.io/instance: ${service}
environment: ${env}
spec:
replicas: ${replicas}
revisionHistoryLimit: 5
selector:
matchLabels:
app.kubernetes.io/name: ${service}
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app.kubernetes.io/name: ${service}
app.kubernetes.io/version: 0.0.0
app.kubernetes.io/instance: ${service}
logging: "false"
armsPilotAutoEnable: "off"
armsPilotCreateAppName: "${service}-${env}"
spec:
serviceAccountName: default
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: gemdale-registry.cn-shenzhen.cr.aliyuncs.com-secret
containers:
- name: ${service}
image: ${image}
imagePullPolicy: IfNotPresent
env:
- name: CONSUL_HOST
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: ELASTIC_APM_SERVER_URLS
value: http://apm-server.logging:8200
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: SERVER_PORT
value: "80"
- name: JAVA_OPTS
value: -Duser.timezone=Asia/Shanghai
- name: WFWAPP
value: wfw-applog
volumeMounts:
- mountPath: /data/appdata/
name: appdata
- mountPath: /data/config-repo/
name: config-repo
- mountPath: /data/logs/
name: logs
- mountPath: /mnt/hgfs/
name: mnt-hgfs
ports:
- containerPort: 80
name: http
resources:
{
}
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: microservice
operator: In
values:
- "true"
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
# Never schedule multiple replicas on the same node
- topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app.kubernetes.io/name: ${service}
app.kubernetes.io/instance: ${service}
volumes:
- hostPath:
path: /data/appdata/
type: DirectoryOrCreate
name: appdata
- hostPath:
path: /data/config-repo/
type: DirectoryOrCreate
name: config-repo
- hostPath:
path: /data/logs/
type: DirectoryOrCreate
name: logs
- hostPath:
path: /mnt/hgfs/
type: DirectoryOrCreate
name: mnt-hgfs
---
apiVersion: v1
kind: Service
metadata:
name: ${service}
labels:
app.kubernetes.io/name: ${service}
app.kubernetes.io/version: 0.0.0
app.kubernetes.io/instance: ${service}
environment: ${env}
spec:
type: ClusterIP
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
selector:
app.kubernetes.io/name: ${service}
app.kubernetes.io/instance: ${service}