使用腾讯云容器服务(TKE)实现应用跨可用区高可用部署之二

使用腾讯云容器服务(TKE)实现应用跨可用区高可用部署之二

在上一篇文章中(使用腾讯云容器服务(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一起部署。

部署的架构如下:

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

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

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

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

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

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

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

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

代码如下:

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管理:

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

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

kubectl get pods -o wide

至此,我们完成了利用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

在创建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大大简化了容器的使用,是您实现快速部署的利器。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区