使用

在上一篇文章中(使用腾讯云容器服务(TKE)实现应用跨可用区高可用部署之一),我们介绍了如何使用腾讯云容器服务的亲和性实现业务跨可用区高可用部署。通过控制台的简单操作,即可实现业务高可用部署。 控制台上实现的亲和性和反亲和性是通过节点亲和性(nodeAffinity)来实现的。

K8S中还支持PodAffinity。在K8S 1.4中引入了Inter-pod affinity和anti-affinity。通过Pod间亲和性和反亲和性,您可以根据节点上已运行的pod上的标签进行调度,而不是基于节点上的标签来约束pod可以调度到哪些节点上。规则的形式是: 一个Pod应该(或不应该)运行在某一个节点X上,如果节点X上已经运行了其他pod,并且这些Pod符合规则Y。 规则Y可以通过LabelSelector语法来表示,LabelSelector是有关联的命名空间列表。与节点(Node)不同,因为pod是运行在命名空间中的(因此pod上的标签也有命名空间属性),pod标签上的lable selecter也必须指定适用于哪些命名空间。从概念上讲,X是一个拓扑域,比如节点(Node),机架,云可用区AZ,云region。您可以使用topologyKey表示拓扑域,该关键字是系统用于表示此类拓扑域的节点标签的关键字。

官方文档的原文如下:

Inter-pod affinity and anti-affinity were introduced in Kubernetes 1.4. Inter-pod affinity and anti-affinity allow you to constrain which nodes your pod is eligible to be scheduled based on labels on pods that are already running on the node rather than based on labels on nodes. The rules are of the form “this pod should (or, in the case of anti-affinity, should not) run in an X if that X is already running one or more pods that meet rule Y”. Y is expressed as a LabelSelector with an associated list of namespaces; unlike nodes, because pods are namespaced (and therefore the labels on pods are implicitly namespaced), a label selector over pod labels must specify which namespaces the selector should apply to. Conceptually X is a topology domain like node, rack, cloud provider zone, cloud provider region, etc. You express it using a topologyKey which is the key for the node label that the system uses to denote such a topology domain.

文档地址:https://kubernetes.io/docs/concepts/configuration/assign-pod-node/

使用Pod affinity实现跨可用区部署

下面我们通过一个例子,具体演示一下如何通过腾讯云容器服务,适用Pod affinity 实现业务亲和性部署。本例子的来源是官网文档的例子。

Web Server通常会有cache,如果web-server适用容器服务做跨可用区分布式部署,那么通常也系统redis能跟随web server一起部署。

部署的架构如下:

dbdfdfa130e38c48eea98e76830269d6.png

dbdfdfa130e38c48eea98e76830269d6.png

Web Server1和Redis1 部署在Node1上, Web Server2 和Redis2部署在Node2上。

下面我们在腾讯云容器服务(TKE)控制台上实现上述部署。

创建容器集群,创建镜像仓库等步骤请参考之前的文章,这里不再赘述。

在deployment中,选择YAML创建资源。

dbdfdfa130e38c48eea98e76830269d6.png

首先创建Redis,我们命名为swagger-cache:

dbdfdfa130e38c48eea98e76830269d6.png

YAML代码如下:

apiVersion: apps/v1beta1

kind: Deployment

metadata:

name: redis-cache

spec:

selector:

matchLabels:

app: swagger-cache

replicas: 2

template:

metadata:

labels:

app: swagger-cache

spec:

affinity:

podAntiAffinity:

requiredDuringSchedulingIgnoredDuringExecution:

- labelSelector:

matchExpressions:

- key: app

operator: In

values:

- swagger-cache

topologyKey: "failure-domain.beta.kubernetes.io/zone"

containers:

containers:

- image: redis:latest

imagePullPolicy: Always

name: swagger-cache

resources:

limits:

cpu: 500m

memory: 1Gi

requests:

cpu: 250m

memory: 256Mi

terminationMessagePath: /dev/termination-log

terminationMessagePolicy: File

dnsPolicy: ClusterFirst

imagePullSecrets:

- name: qcloudregistrykey

- name: tencenthubkey

restartPolicy: Always

schedulerName: default-scheduler

securityContext: {}

terminationGracePeriodSeconds: 30

dbdfdfa130e38c48eea98e76830269d6.png

创建好之后查看pod管理,可以看到两个pod分布到了2个节点上;

然后我们创建swaggerui应用。同样适用YAML创建。

dbdfdfa130e38c48eea98e76830269d6.png

代码如下:

apiVersion: apps/v1beta1

kind: Deployment

metadata:

name: swagger-web

spec:

selector:

matchLabels:

app: swagger-web

replicas: 2

template:

metadata:

labels:

app: swagger-web

spec:

affinity:

podAntiAffinity:

requiredDuringSchedulingIgnoredDuringExecution:

- labelSelector:

matchExpressions:

- key: app

operator: In

values:

- swagger-web

topologyKey: "failure-domain.beta.kubernetes.io/zone"

podAffinity:

requiredDuringSchedulingIgnoredDuringExecution:

- labelSelector:

matchExpressions:

- key: app

operator: In

values:

- swagger-cache

topologyKey: "failure-domain.beta.kubernetes.io/zone"

containers:

- env:

- name: PATH

value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

- name: NGINX_VERSION

value: 1.15.9

- name: API_KEY

value: '**None**'

- name: SWAGGER_JSON

value: /app/swagger.json

- name: PORT

value: "8080"

- name: BASE_URL

image: ccr.ccs.tencentyun.com/zehua/swaggerui:1.2

imagePullPolicy: IfNotPresent

name: swagger-ui

resources:

limits:

cpu: 500m

memory: 1Gi

requests:

cpu: 250m

memory: 256Mi

terminationMessagePath: /dev/termination-log

terminationMessagePolicy: File

dnsPolicy: ClusterFirst

imagePullSecrets:

- name: qcloudregistrykey

- name: tencenthubkey

restartPolicy: Always

schedulerName: default-scheduler

securityContext: {}

terminationGracePeriodSeconds: 30

创建好之后查看pod管理:

dbdfdfa130e38c48eea98e76830269d6.png

可以看到两个swaggerui也分布到了跨可用区的两个节点上。

适用kubectl查看pod的分布情况:

kubectl get pods -o wide

dbdfdfa130e38c48eea98e76830269d6.png

至此,我们完成了利用Pod affinity实现跨可用区的高可用部署。下面我们具体解释一下是如何实现的。

部署原理分析

在创建redis时,我们使用pod anti-affinity的特性:

spec:

affinity:

podAntiAffinity:

requiredDuringSchedulingIgnoredDuringExecution:

- labelSelector:

matchExpressions:

- key: app

operator: In

values:

- swagger-cache

topologyKey: "failure-domain.beta.kubernetes.io/zone"

podAntiAffinity指定了redis的两个pod的反亲和性,要分布到标签为app=swagger-cache的不同节点上。 并且topologyKey: "failure-domain.beta.kubernetes.io/zone" 有两个值:800002和800003,分布对应腾讯云北京二区、北京三区。这样保证了两个pod分布到不同的可用区。

kubectl get nodes --show-labels

dbdfdfa130e38c48eea98e76830269d6.png

在创建swagger-cache时,我们使用了pod-affinity和pod-anti-affinity

spec:

affinity:

podAntiAffinity:

requiredDuringSchedulingIgnoredDuringExecution:

- labelSelector:

matchExpressions:

- key: app

operator: In

values:

- swagger-web

topologyKey: "failure-domain.beta.kubernetes.io/zone"

podAffinity:

requiredDuringSchedulingIgnoredDuringExecution:

- labelSelector:

matchExpressions:

- key: app

operator: In

values:

- swagger-cache

topologyKey: "failure-domain.beta.kubernetes.io/zone"

首先podAntiAffinity指定了两个swagger-web的反亲和性, 部署到标签为App=swagger-web的两台不同节点上。 然后使用podAffinity指定swagger-web和swagger-cache的亲和性部署。

在实际应用中,可以使用podAntiAffinity和podAffinity实现复杂的部署关系。腾讯云容器服务TKE大大简化了容器的使用,是您实现快速部署的利器。

注明:本文来自投稿,不代表服务器文档网立场,如若转载,请注明出处:https://www.fwqwd.com/11910.html

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐