简介: 混合云K8s容器化应用弹性伸缩实战

1. 前提条件

本最佳实践的软件环境要求如下:
应用环境:
①容器服务ACK基于专有云V3.10.0版本。
②公共云云企业网服务CEN。
③公共云弹性伸缩组服务ESS。
配置条件:
1)使用专有云的容器服务或者在ECS上手动部署敏捷PaaS。
2)开通云专线,打通容器服务所在VPC与公共云上的VPC。
3)开通公共云弹性伸缩组服务(ESS)。

2. 背景信息

本实践基于K8s的业务集群运行在专有云上,对测试业务进行压力测试,主要基于以下三种产品和能力:
①利用阿里云的云企业网专线打通专有云和公共云,实现两朵云上VPC网络互通。
②利用K8s(Kubernetes)的HPA能力,实现容器的水平伸缩。
③利用K8s的Cluster Autoscaler和阿里云弹性伸缩组ESS能力实现节点的自动伸缩。

HPA(Horizontal Pod Autoscaler)是K8s的一种资源对象,能够根据CPU、内存等指标对statefulset、deployment等对象中的pod数量进行动态伸缩,使运行在上面的服务对指标的变化有一定的自适应能力。

当被测试业务指标达到上限时,触发HPA自动扩容业务pod;当业务集群无法承载更多pod时,触发公共云的ESS服务,在公共云内扩容出ECS并自动添加到专有云的K8s集群。


图 1:架构原理图

3. 配置HPA

本示例创建了一个支持HPA的nginx应用,创建成功后,当Pod的利用率超过本例中设置的20%利用率时,则会进行水平扩容,低于20%的时候会进行缩容。

1.若使用自建K8s集群,则通过yaml文件配置HPA

1)创建一个nginx应用,必须为应用设置request值,否则HPA不会生效。

apiVersion:
app/v1beta2
kind: Deployment
spec:
template:
metadata:
creationTimestamp: null
labels:
app: hpa-test
spec:
dnsPolicy: ClusterFirst
terminationGracePeriodSeconds:30
containers:
image: '192.168.**.***:5000/admin/hpa-example:v1'
imagePullPolicy: IfNotPresent
terminationMessagePolicy:File
terminationMessagePath:/dev/termination-log
name: hpa-test
resources:
requests:
cpu: //必须设置request值
securityContext: {}
restartPolicy:Always
schedulerName:default-scheduler
replicas: 1
selector:
matchLabels:
app: hpa-test
revisionHistoryLimit: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
progressDeadlineSeconds: 600

2)创建HPA。

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
annotations:
autoscaling.alpha.kubernetes.io/conditions:'[{"type":"AbleToScale","status":"True","lastTransitionTime":"2020-04-29T06:57:28Z","reason":"ScaleDownStabilized","message":"recent
recommendations were higher than current one, applying the highest recent
recommendation"},{"type":"ScalingActive","status":"True","lastTransitionTime":"2020-04-29T06:57:28Z","reason":"ValidMetricFound","message":"theHPA
was able to successfully calculate a replica count from cpu resource
utilization(percentage of
request)"},{"type":"ScalingLimited","status":"False","lastTransitionTime":"2020-04-29T06:57:28Z","reason":"DesiredWithinRange","message":"thedesired
count is within the acceptable range"}]'
autoscaling.alpha.kubernetes.io/currentmetrics:'[{"type":"Resource","resource":{"name":"cpu","currentAverageUtilization":0,"currentAverageValue":"0"}}]' creationTimestamp: 2020-04-29T06:57:13Z
name: hpa-test
namespace: default
resourceVersion: "3092268"
selfLink:
/apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/hpa01
uid: a770ca26-89e6-11ea-a7d7-00163e0106e9
spec:
maxReplicas: //设置pod数量
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1beta2
kind: Deployment
name: centos
targetCPUUtilizationPercentage://设置CPU阈值
2.若使用阿里云容器服务,需要在部署应用时选择配置HPA


图2:访问设置

4. 配置Cluster Autoscaler

资源请求(Request)的正确、合理设置,是弹性伸缩的前提条件。节点自动伸缩组件基于K8s资源调度的分配情况进行伸缩判断,节点中资源的分配通过资源请(Request)进行计算。

当Pod由于资源请求(Request)无法满足并进入等待(Pending)状态时,节点自动伸缩组件会根据弹性伸缩组配置信息中的资源规格以及约束配置,计算所需的节点数目。

如果可以满足伸缩条件,则会触发伸缩组的节点加入。而当一个节点在弹性伸缩组中且节点上Pod的资源请求低于阈值时,节点自动伸缩组件会将节点进行缩容。

1.配置弹性伸缩组ESS

1)创建ESS弹性伸缩组,记录最小实例数和最大实例数。


图3:修改伸缩组

2)创建伸缩配置,记录伸缩配置的id。


图4:伸缩配置

#!/bin/sh
yum install -y ntpdate && ntpdate -u ntp1.aliyun.com && curl http:// example.com/public/hybrid/attach_local_node_aliyun.sh | bash -s -- --docker-version 17.06.2-ce-3 --token
9s92co.y2gkocbumal4fz1z --endpoint 192.168.**.***:6443 --cluster-dns 10.254.**.**
--region cn-huhehaote
echo "{" > /etc/docker/daemon.json
echo "\"registry-mirrors\": [" >>
/etc/docker/daemon.json
echo "\"https://registry-vpc.cn-huhehaote.aliyuncs.com\"" >> /etc/docker/daemon.json
echo "]," >> /etc/docker/daemon.json
echo "\"insecure-registries\": [\"https://192.168.**.***:5000\"]" >> /etc/docker/daemon.json
echo "}" >> /etc/docker/daemon.json
systemctl restart docker
2.K8s集群部署autoscaler
kubectl apply -f ca.yml

参考ca.yml创建autoscaler,注意修改如下配置与实际环境相对应。

access-key-id: "TFRBSWlCSFJyeHd2QXZ6****"
access-key-secret: "bGIyQ3NuejFQOWM0WjFUNjR4WTVQZzVPRXND****"
region-id: "Y24taHVoZWhh****"

ca.yal代码如下:

---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-addon: cluster-autoscaler.addons.k8s.io
k8s-app: cluster-autoscaler
name: cluster-autoscaler
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-autoscaler
labels:
k8s-addon: cluster-autoscaler.addons.k8s.io
k8s-app: cluster-autoscaler
rules:
- apiGroups: [""]
resources: ["events","endpoints"]
verbs: ["create", "patch"]
- apiGroups: [""]
resources: ["pods/eviction"]
verbs: ["create"]
- apiGroups: [""]
resources: ["pods/status"]
verbs: ["update"]
- apiGroups: [""]
resources: ["endpoints"]
resourceNames: ["cluster-autoscaler"]
verbs: ["get","update"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["watch","list","get","update"]
- apiGroups: [""]
resources: ["pods","services","replicationcontrollers","persistentvolumeclaims","persistentvolumes"]
verbs: ["watch","list","get"]
- apiGroups: ["extensions"]
resources: ["replicasets","daemonsets"]
verbs: ["watch","list","get"]
- apiGroups: ["policy"]
resources: ["poddisruptionbudgets"]
verbs: ["watch","list"]
- apiGroups: ["apps"]
resources: ["statefulsets"]
verbs: ["watch","list","get"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["watch","list","get"] ---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cluster-autoscaler
namespace: kube-system
labels:
k8s-addon: cluster-autoscaler.addons.k8s.io
k8s-app: cluster-autoscaler
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["create","list","watch"]
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["cluster-autoscaler-status", "cluster-autoscaler-priority-expander"]
verbs: ["delete","get","update","watch"] ---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-autoscaler
labels:
k8s-addon: cluster-autoscaler.addons.k8s.io
k8s-app: cluster-autoscaler
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-autoscaler
subjects:
- kind: ServiceAccount
name: cluster-autoscaler
namespace: kube-system ---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: cluster-autoscaler
namespace: kube-system
labels:
k8s-addon: cluster-autoscaler.addons.k8s.io
k8s-app: cluster-autoscaler
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: cluster-autoscaler
subjects:
- kind: ServiceAccount
name: cluster-autoscaler
namespace: kube-system
---
apiVersion: v1
kind: Secret
metadata:
name: cloud-config
namespace: kube-system
type: Opaque
data:
access-key-id: "TFRBSWlCSFJyeHd2********"
access-key-secret: "bGIyQ3NuejFQOWM0WjFUNjR4WTVQZzVP*********"
region-id: "Y24taHVoZW********" ---
apiVersion: apps/v1
kind: Deployment
metadata:
name: cluster-autoscaler
namespace: kube-system
labels:
app: cluster-autoscaler
spec:
replicas: 1
selector:
matchLabels:
app: cluster-autoscaler
template:
metadata:
labels:
app: cluster-autoscaler
spec:
dnsConfig:
nameservers:
- 100.XXX.XXX.XXX
- 100.XXX.XXX.XXX
nodeSelector:
ca-key: ca-value
priorityClassName: system-cluster-critical
serviceAccountName: admin
containers:
- image: 192.XXX.XXX.XXX:XX/admin/autoscaler:v1.3.1-7369cf1
name: cluster-autoscaler
resources:
limits:
cpu: 100m
memory: 300Mi
requests:
cpu: 100m
memory: 300Mi
command:
- ./cluster-autoscaler
- '--v=5'
- '--stderrthreshold=info'
- '--cloud-provider=alicloud'
- '--scan-interval=30s'
- '--scale-down-delay-after-add=8m'
- '--scale-down-delay-after-failure=1m'
- '--scale-down-unready-time=1m'
- '--ok-total-unready-count=1000'
- '--max-empty-bulk-delete=50'
- '--expander=least-waste'
- '--leader-elect=false'
- '--scale-down-unneeded-time=8m'
- '--scale-down-utilization-threshold=0.2'
- '--scale-down-gpu-utilization-threshold=0.3'
- '--skip-nodes-with-local-storage=false'
- '--nodes=0:5:asg-hp3fbu2zeu9bg3clraqj'
imagePullPolicy: "Always"
env:
- name: ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: cloud-config
key: access-key-id
- name: ACCESS_KEY_SECRET
valueFrom:
secretKeyRef:
name: cloud-config
key: access-key-secret
- name: REGION_ID
valueFrom:
secretKeyRef:
name: cloud-config
key: region-id

5. 执行结果

模拟业务访问:

启动busybox镜像,在pod内执行如下命令访问以上应用的service,可以同时启动多个pod增加业务负载。while true;do wget -q -O- http://hpa-test/index.html;done

观察HPA:

加压前


图 5:加压前

加压后
当CPU值达到阈值后,会触发pod的水平扩容。


图 6:加压后1

图 7:加压后2

观察Pod:

当集群资源不足时,新扩容出的pod处于pending状态,此时将触发cluster autoscaler,自动扩容节点。


图8:伸缩活动

本文为阿里云原创内容,未经允许不得转载。

混合云K8s容器化应用弹性伸缩实战的更多相关文章

  1. 用户案例 | 腾讯小视频&转码平台云原生容器化之路

    作者 李汇波,腾讯业务运维高级工程师,目前就职于TEG 云架构平台部 技术运营与质量中心,现负责微信.QQ社交类业务的视频转码运维. 摘要 随着短视频兴起和快速发展,对于视频转码处理的需求也越来越多. ...

  2. AMS 新闻视频广告的云原生容器化之路

    作者 卓晓光,腾讯广告高级开发工程师,负责新闻视频广告整体后台架构设计,有十余年高性能高可用海量后台服务开发和实践经验.目前正带领团队完成云原生技术栈的全面转型. 吴文祺,腾讯广告开发工程师,负责新闻 ...

  3. 最佳案例 | QQ 相册云原生容器化之路

    关于我们 更多关于云原生的案例和知识,可关注同名[腾讯云原生]公众号~ 福利: ①公众号后台回复[手册],可获得<腾讯云原生路线图手册>&<腾讯云原生最佳实践>~ ②公 ...

  4. 最佳案例 | 游戏知几 AI 助手的云原生容器化之路

    作者 张路,运营开发专家工程师,现负责游戏知几 AI 助手后台架构设计和优化工作. 游戏知几 随着业务不断的拓展,游戏知几AI智能问答机器人业务已经覆盖了自研游戏.二方.海外的多款游戏.游戏知几研发团 ...

  5. 【阿里云产品公测】弹性伸缩服务ESS之试用初体验

    弹性伸缩服务ESS之试用初体验 作者:云郎 2014/10/15 阿里云弹性伸缩服务(Elastic Scaling Service)是根据用户的业务需求和策略,自动调整其弹性计算服务器(ECS)的管 ...

  6. 成本降低40%、资源利用率提高20%的 AI 应用产品云原生容器化之路

    作者 郭云龙,腾讯云高级工程师,目前就职于 CSIG 云产品三部-AI 应用产品中心,现负责中心后台业务框架开发. 导语 为了满足 AI 能力在公有云 SaaS 场景下,服务和模型需要快速迭代交付的需 ...

  7. [k8s]容器化node-expolore(9100)+cadvisor(8080)+prometheus(9090) metric搜集,grafana展示

    Prometheus 的核心,多维数据模型 传统监控工具统计数据方式 指标多 - 需求1,统计app1-3,的(总)内存,则定义3个指标 container.memory_usage_bytes.we ...

  8. 在阿里云上进行Docker集群的自动弹性伸缩

    摘要: 在刚刚结束的云栖大会上,阿里云容器服务演示了容器的自动弹性伸缩,能够从容应对互联网应用的峰值流量.阿里云容器服务不仅支持容器级别的自动弹性伸缩,也支持集群节点级别的自动弹性伸缩.从而真正做到从 ...

  9. 【阿里云ACP】-04(负载均衡SLB、弹性伸缩AS内容分发、网络与VPC)

    阿里云例题介绍-CDN F公司新推出一款手机APP,将安装包链接挂在公司的官网(基于云服务器ECS实例)进行下载(安装包大小:6Mb),上线前两个月下载速度还能接受.自从上周公司在CCTV做了一次广告 ...

  10. 腾讯云TKE-基于 Cilium 统一混合云容器网络(下)

    前言 在 腾讯云TKE - 基于 Cilium 统一混合云容器网络(上) 中,我们介绍 TKE 混合云的跨平面网络互通方案和 TKE 混合云 Overlay 网络方案.公有云 TKE 集群添加第三方 ...

随机推荐

  1. 9、Azure DevOps安装部署篇

    下载地址 微软默认提供了两个版本的下载:Azure DevOps Server和Azure DevOps Server Express . Azure DevOps Server 提供90天试用的收费 ...

  2. webpack 项目接入Vite的通用方案介绍(下)

    愿景 希望通过此系列文章,能给读者提供一个存/增量项目接入Vite的点子,起抛砖引玉的作用,减少这方面能力的建设成本 在阐述过程中同时也会逐渐完善webpack-vite-serve这个工具 读者可直 ...

  3. [leetcode 496. 下一个更大元素 I] 单调栈

    单调栈的写法: import java.util.ArrayDeque; import java.util.Deque; import java.util.HashMap; import java.u ...

  4. C#实时监测文件夹变化

    在开发各种应用程序时,我们经常需要对文件系统中的文件或文件夹进行实时监测,以便在文件内容改变.文件被创建或删除时能够及时做出反应.在 C# 中,System.IO.FileSystemWatcher ...

  5. C++中虚表是什么

    虚函数表,以及虚函数指针是实现多态性(Polymorphism)的关键机制.多态性允许我们通过基类的指针或引用来调用派生类的函数 定义 虚函数(Virtual Function) 定义:类中使用vir ...

  6. 天天用defineEmits宏函数,竟然不知道编译后是vue2的选项式API?

    前言 我们每天都在使用 defineEmits 宏函数,但是你知道defineEmits 宏函数经过编译后其实就是vue2的选项式API吗?通过回答下面两个问题,我将逐步为你揭秘defineEmits ...

  7. Android打造万能自定义阴影控件

    目录介绍 01.阴影效果有哪些实现方式 02.实现阴影效果Api 03.设置阴影需要注意哪些 04.常见Shape实现阴影效果 05.自定义阴影效果控件 06.如何使用该阴影控件 07.在recycl ...

  8. 记录--7 个沙雕又带有陷阱的 JS 面试题

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 为了保证的可读性,本文采用意译而非直译. 在 JS 面试中,经常会看到一些简单而又沙雕的题目,这些题目包含一些陷阱,但这些在我们规范的编码 ...

  9. Ficow 陪你看 WWDC 2022

    本文首发于 Ficow Shen's Blog,原文地址: WWDC22 - Xcode 14 新特性. 内容概览 前言 用好过滤器 Recap,节约你的宝贵时间 Essential,取其精华 必看内 ...

  10. 工作中常用且容易遗忘的 CSS 样式清单

    注:本文转载自公众号 Vue中文社区的一篇文章 1.文字超出部分显示省略号 单行文本的溢出显示省略号(一定要有宽度)  p{    width:200rpx;    overflow: hidden; ...