为什么需要灰度发布

灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。

总结下一些应用场景:

  • 微服务依赖很多组件,需要在实际环境验证
  • 部署新功能有风险,然后可以通过导流一小部分用户实际使用,来减小风险
  • 让特定的用户访问新版本,比如部署一个版本,只让测试使用
  • A/B Testing,部署两个版本,进行版本对比,比如验证两个推荐服务的推荐效果

灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。

ambassador介绍

ambassador[æmˈbæsədər],是Kubernetes微服务 API gateway,基于Envoy Proxy。

Open Source Kubernetes-Native API Gateway built on the Envoy Proxy

官方地址:

https://www.getambassador.io/

部署ambassador

按官网提示部署ambassador

cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: Service
metadata:
labels:
service: ambassador-admin
name: ambassador-admin
spec:
type: NodePort
ports:
- name: ambassador-admin
port: 8877
targetPort: 8877
selector:
service: ambassador
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: ambassador
rules:
- apiGroups: [""]
resources: [ "endpoints", "namespaces", "secrets", "services" ]
verbs: ["get", "list", "watch"]
- apiGroups: [ "getambassador.io" ]
resources: [ "*" ]
verbs: ["get", "list", "watch"]
- apiGroups: [ "apiextensions.k8s.io" ]
resources: [ "customresourcedefinitions" ]
verbs: ["get", "list", "watch"]
- apiGroups: [ "networking.internal.knative.dev" ]
resources: [ "clusteringresses", "ingresses" ]
verbs: ["get", "list", "watch"]
- apiGroups: [ "networking.internal.knative.dev" ]
resources: [ "ingresses/status", "clusteringresses/status" ]
verbs: ["update"]
- apiGroups: [ "extensions" ]
resources: [ "ingresses" ]
verbs: ["get", "list", "watch"]
- apiGroups: [ "extensions" ]
resources: [ "ingresses/status" ]
verbs: ["update"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: ambassador
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: ambassador
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ambassador
subjects:
- kind: ServiceAccount
name: ambassador
namespace: kube-system
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: authservices.getambassador.io
spec:
group: getambassador.io
version: v1
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: authservices
singular: authservice
kind: AuthService
categories:
- ambassador-crds
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: consulresolvers.getambassador.io
spec:
group: getambassador.io
version: v1
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: consulresolvers
singular: consulresolver
kind: ConsulResolver
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: kubernetesendpointresolvers.getambassador.io
spec:
group: getambassador.io
version: v1
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: kubernetesendpointresolvers
singular: kubernetesendpointresolver
kind: KubernetesEndpointResolver
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: kubernetesserviceresolvers.getambassador.io
spec:
group: getambassador.io
version: v1
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: kubernetesserviceresolvers
singular: kubernetesserviceresolver
kind: KubernetesServiceResolver
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: mappings.getambassador.io
spec:
group: getambassador.io
version: v1
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: mappings
singular: mapping
kind: Mapping
categories:
- ambassador-crds
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: modules.getambassador.io
spec:
group: getambassador.io
version: v1
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: modules
singular: module
kind: Module
categories:
- ambassador-crds
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ratelimitservices.getambassador.io
spec:
group: getambassador.io
version: v1
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: ratelimitservices
singular: ratelimitservice
kind: RateLimitService
categories:
- ambassador-crds
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tcpmappings.getambassador.io
spec:
group: getambassador.io
version: v1
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: tcpmappings
singular: tcpmapping
kind: TCPMapping
categories:
- ambassador-crds
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlscontexts.getambassador.io
spec:
group: getambassador.io
version: v1
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: tlscontexts
singular: tlscontext
kind: TLSContext
categories:
- ambassador-crds
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tracingservices.getambassador.io
spec:
group: getambassador.io
version: v1
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: tracingservices
singular: tracingservice
kind: TracingService
categories:
- ambassador-crds
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: logservices.getambassador.io
spec:
group: getambassador.io
version: v1
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: logservices
singular: logservice
kind: LogService
categories:
- ambassador-crds
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ambassador
spec:
replicas: 3
selector:
matchLabels:
service: ambassador
template:
metadata:
annotations:
sidecar.istio.io/inject: "false"
"consul.hashicorp.com/connect-inject": "false"
labels:
service: ambassador
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
service: ambassador
topologyKey: kubernetes.io/hostname
serviceAccountName: ambassador
containers:
- name: ambassador
image: quay.azk8s.cn/datawire/ambassador:0.86.1
resources:
limits:
cpu: 1
memory: 400Mi
requests:
cpu: 200m
memory: 100Mi
env:
- name: AMBASSADOR_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- name: http
containerPort: 8080
- name: https
containerPort: 8443
- name: admin
containerPort: 8877
livenessProbe:
httpGet:
path: /ambassador/v0/check_alive
port: 8877
initialDelaySeconds: 30
periodSeconds: 3
readinessProbe:
httpGet:
path: /ambassador/v0/check_ready
port: 8877
initialDelaySeconds: 30
periodSeconds: 3
volumeMounts:
- name: ambassador-pod-info
mountPath: /tmp/ambassador-pod-info
volumes:
- name: ambassador-pod-info
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
restartPolicy: Always
securityContext:
runAsUser: 8888
---
apiVersion: v1
kind: Service
metadata:
name: ambassador
spec:
type: NodePort
externalTrafficPolicy: Local
ports:
- port: 80
targetPort: 8080
selector:
service: ambassador EOF

为了方便访问网关,生成一个ingress:


apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
kubernetes.io/tls-acme: 'true'
name: ambassador
spec:
rules:
- host: ambassador.iflyresearch.com
http:
paths:
- backend:
serviceName: ambassador
servicePort: 80
path: /

ambassador 配置

ambassador 使用envoy来实现相关的负载,而envoy类似nginx。ambassador的原理大概是读取service里的配置,然后自动生成envoy的配置,当service变更时,动态更新envoy的配置并重启,所以ambassador需要可以访问服务API。

ambassador 的配置是放到metadata的annotations,以getambassador.io/config开头:

  annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v0
kind: Mapping
name: {{ .Values.service.name }}_mapping
prefix: /{{ .Values.service.prefix }}
service: {{ .Values.service.name }}.{{ .Release.Namespace }}

profix指定如何访问服务,service指定指向那个服务。注意,需要加上namespace名称,否则容易报找不到后端。

ambassador 灰度

ambassador实现灰度可以根据weight权重,或者指定匹配特定的header来实现。

根据weight进行灰度

用法:

部署一个新版本的service,prefix和之前老服务保持一致,但是配置weight,比如20,这样20%的流量会流转到新服务,这样实现A/B Test

---
apiVersion: v1
kind: Service
metadata:
name: svc-gray
namespace: default
annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v0
kind: Mapping
name: svc1_mapping
prefix: /svc/
service: service-gray
weight: 20
spec:
selector:
app: testservice
ports:
- port: 8080
name: service-gray
targetPort: http-api

根据请求头 header 进行灰度 (regex_headers 正则匹配)

部署一个新版本,只需要特定的用户才能访问,可以通过该方案来实现。

例如:

---
apiVersion: v1
kind: Service
metadata:
name: svc-gray
namespace: default
annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v0
kind: Mapping
name: svc1_mapping
prefix: /svc/
service: service-gray
headers:
gray: true
spec:
selector:
app: testservice
ports:
- port: 8080
name: service-gray
targetPort: http-api

访问时,当指定gray: true时,访问灰度版本,可以用postman来测试:


作者:Jadepeng

出处:jqpeng的技术记事本--http://www.cnblogs.com/xiaoqi

您的支持是对博主最大的鼓励,感谢您的认真阅读。

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

基于ambassador实现K8S灰度发布的更多相关文章

  1. ASP.NET Core on K8S学习之旅(14)Ingress灰度发布

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 之前一篇介绍了Ingress的基本概念和Nginx Ingress的基本配置和 ...

  2. K8S基于ingress-nginx实现灰度发布

    之前介绍过使用ambassador实现灰度发布,今天介绍如何使用ingre-nginx实现. 介绍 Ingress-Nginx 是一个K8S ingress工具,支持配置 Ingress Annota ...

  3. K8s 1.18.6版本基于 ingress-nginx 实现金丝雀发布(灰度发布)

    K8s 1.18.6版本基于 ingress-nginx 实现金丝雀发布(灰度发布) 环境 软件 版本 kubernetes v1.18.6 nginx-ingress-controller 0.32 ...

  4. Istio最佳实践:在K8s上通过Istio服务网格进行灰度发布

    Istio是什么? Istio是Google继Kubernetes之后的又一开源力作,主要参与的公司包括Google,IBM,Lyft等公司.它提供了完整的非侵入式的微服务治理解决方案,包含微服务的管 ...

  5. Knativa 基于流量的灰度发布和自动弹性实践

    作者 | 李鹏(元毅) 来源 | Serverless 公众号 一.Knative Knative 提供了基于流量的自动扩缩容能力,可以根据应用的请求量,在高峰时自动扩容实例数:当请求量减少以后,自动 ...

  6. k8s+istio:流量控制之灰度发布

    通过Kubernetes+Istio的流量控制实现灰度发布,主要演示通过流量权重实现蓝绿,通过http自定义头实现金丝雀 准备环境 k8s和istio不想自己装的话可以在云上买个按量付费集群,用完即删 ...

  7. Istio 太复杂?KubeSphere基于Ingress-Nginx实现灰度发布

    在 Bookinfo 微服务的灰度发布示例 中,KubeSphere 基于 Istio 对 Bookinfo 微服务示例应用实现了灰度发布.有用户表示自己的项目还没有上 Istio,要如何实现灰度发布 ...

  8. k8s实现灰度发布

    灰度发布在实际生产部署中是经常被使用的方式,常规的方法是手动从前端LB(负载均衡)上将后端服务器摘掉,然后,停服务,最后上传代码,完成软连接更新.在使用CI/CD工具时,这个过程变得自动化了,我们只需 ...

  9. 基于 Istio 与 Kubernetes 对应用进行灰度发布与 Tracing

    灰度发布,是指在黑与白之间,能够平滑过渡的一种发布方式.通俗来说,即让产品的迭代能够按照不同的灰度策略对新版本进行线上环境的测试,灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以对新版本进行测试 ...

随机推荐

  1. 2019-10-22-Roslyn-打包自定义的文件到-NuGet-包

    title author date CreateTime categories Roslyn 打包自定义的文件到 NuGet 包 lindexi 2019-10-22 19:45:34 +0800 2 ...

  2. SDUT-3342_数据结构实验之二叉树三:统计叶子数

    数据结构实验之二叉树三:统计叶子数 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 已知二叉树的一个按先序遍历输入的字符 ...

  3. SDUT-2117_数据结构实验之链表二:逆序建立链表

    数据结构实验之链表二:逆序建立链表 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 输入整数个数N,再输入N个整数,按照 ...

  4. Python 基础 --初识Python

    python的起源 python是一门 解释型弱类型编程语言. 特点: 简单.明确.优雅 python的解释器 CPython. 官方提供的. 内部使用c语言来实现 PyPy. 一次性把我们的代码解释 ...

  5. 1、Ubuntu 16.04 安装.net core

    Register the Microsoft key register the product repository Install required dependencies 参考网址:https: ...

  6. hdu 3272 Mission Impossible

    Mission Impossible Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  7. js键盘按下移动元素

    文章地址 https://www.cnblogs.com/sandraryan/ 功能: 点击上下左右按钮,移动元素 <!DOCTYPE html> <html lang=" ...

  8. tp5 select出来数据集(对象)转成数组

    1.先在数据库配置文件中 //数据集返回类型 'resultset_type' => 'collection', 2.在使用时, 使用 toArray() 方法 //查询数据库 $news = ...

  9. P1002 Hello,World!

    题目描述 输出"Hello Wolrd!". 输入格式 无. 输出格式 输出一行"Hello World!". 样例输入 无. 样例输出 Hello World ...

  10. HDU 1711 Number Sequence (KMP 入门)

    Number Sequence Problem Description Given two sequences of numbers : a[1], a[2], ...... , a[N], and ...