Istio是第二代Service Mesh(服务网格)的主流方案之一,它的设计初衷在于加强微服务之间通信的稳定性,透明度和安全性。Istio拦截部署在容器平台(如Kubertenes)服务的内部外部流量。
虽然Istio支持如加密服务间的通信,参数日志自动收集,加强的访问控制策略,限速,配额管理等诸多功能,我们此次教程只专注于流量管理这个特性。
Istio使得DevOps团队通过创建规则,让流量可以被智能的路由到内部的服务。Istio也使得类似熔断,超时,重试这样的服务属性相关的设置变得极为简单,也可以通过一系列的参数设置实现蓝绿部署和金丝雀实施(canary rollouts)。
这个教程的目标就是帮助你理解如何配置Istio实现Kubernetes平台上微服务的蓝绿部署。你只要具备Kubenetes pods ,service相关的基础知识,就能看懂这个教程。我们会从Minikube到Istio再到简单的应用,逐一进行配置。
这个教程会分成四个步骤:Minikube的安装;Istio的安装和验证;同一个应用的两个不同版本的安装以及蓝绿部署服务的最终配置。我们已经准备好了两个简单的容器镜像,他们分别用于表蓝色(V1)和绿色(V2)的发布。
第一步:安装Minikube
为了减少依赖性,我们用Minikube作为实验平台。因为我们需要对Minikube做定制的配置,所以先删除现有的配置然后设置一些参数并重启集群。
$ minikube start --memory=8192 --cpus=4 --kubernetes-version=v1.10.0 \
--extra-config=controller-manager.cluster-signing-cert-file="/var/lib/localkube/certs/ca.crt" \
--extra-config=controller-manager.cluster-signing-key-file="/var/lib/localkube/certs/ca.key" \
--vm-driver=virtualbox
在Minikube中运行Istio需要至少8GB内存和四核CPU。这里我们等待集群启动。
第二步:安装 Istio
Kubernetes启动以后,开始安装Istio。我们通过下面的步骤来做配置。
$ curl -L https://git.io/getLatestIstio | sh -
你会发现一个叫istio-1.0.2的文件夹,所有的命令也都在这个目录下运行。可以把istio-1.0.2/bin这个目录加到PATH变量中,这样敲命令就更简单了。
既然我们已经在Minikube中运行了Istio,进行下一步之前我们还需要做个小调整:把Ingress网关的服务类型从LoadBalancer改成NodePort。
打开istio-1.0.2/install/kubernetes/istio-demo.yaml,搜索LoadBalancer关键字,然后把它改成NodePort。
Istio有很多针对Kubernetes的自定义资源类型Custom Resource Definitions(CRD)。这些资源类型帮助我们利用kubectl操作虚拟服务,规则,网关以及其他Istio相关的对象。在部署Service Mesh(服务网格)之前,我们先要安装自定义资源类型。
$ kubectl apply -f install/kubernetes/helm/istio/templates/crds.yaml
最终我们开始在Kubernetes上安装Istio。
$ kubectl apply -f install/kubernetes/istio-demo.yaml
上面的步骤创建了一个叫istio-system的新命名空间,在这个命名空间里我们会继续部署更多的对象。
我们能发现很多服务都在istio-system这个命名空间中自动创建了。
几分钟以后,你会看到Istio部署了很多Pod。我们可以通过运行kubectl get pods -n=istio-system来验证。
当所有的Pod状态都是运行或者完成的状态,就意味着已经成功的安装和配置了Istio。
现在我们就已经可以开始部署和配置蓝绿服务的参数了。
第三步:部署同一个应用的两个版本
我们构建了简单的基于Nginx的Docker镜像来作为应用案例:janakiramm/myapp:v1和janakiramm/myapp:v2。部署完成之后,这两个版本的Nginx会分别显示蓝色或者绿色背景的静态页面。我们用这些图像来完成我们的教程。
apiVersion: v1
kind: Service
metadata:
name: myapp
labels:
app: myapp
spec:
type: ClusterIP
ports:
- port: 80
name: http
selector:
app: myapp
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myapp-v1
spec:
replicas: 1
template:
metadata:
labels:
app: myapp
version: v1
spec:
containers:
- name: myapp
image: janakiramm/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myapp-v2
spec:
replicas: 1
template:
metadata:
labels:
app: myapp
version: v2
spec:
containers:
- name: myapp
image: janakiramm/myapp:v2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
你可以从GitHub[1]获得相关的YAML文件。
我们先从创建YAML文件开始,来定义V1和V2版本Nginx的部署,同时也设置集群IP把服务暴露出来。请注意我们用不同的标签来区分Pods——app和版本。因为两次部署的版本号不一样,app名字可以相同。
这是Istio所希望的,像单一的app那样处理它们,用不同的个版本来区分。
集群的服务定义也是一样的,标签app: myapp关联了基于不同版本所创建的Pod。
通过kubectl来创建deployment和service。注意deployment和service是Kubernetes的相关术语,和Istio没有关系。唯一和Istio的关联是我们为deployment和service创建标签的方式。
$ kubectl apply -f myapp.yaml
配置Istio之前,我们先来检查一下app的版本。我们可以通过port-forward deployments访问Pod。通过运行下面的命令访问V1的8080端口。准备好CTRL+C吧。
$ kubectl port-forward deployment/myapp-v1 8080:80
运行下面的命令访问V2的8081端口,继续CTRL+C。
$ kubectl port-forward deployment/myapp-v2 8081:80
第四步:配置蓝绿部署
我们的实验目标是让流量有选择的访问某一个部署,而且不能有服务停止。为了达到这目的,我们要告诉Istio依照权重来路由流量。
为了达到这个效果我们需要设置三个对象:
网关
Istio网关描述了在网格边界的负载均衡器如何处理进出的HTTP/TCP连接。着重描述了哪些端口应该被暴露出来,有哪些协议可以用,负载均衡器的SNI配置等等。接下来,我们把网关指向默认的Ingress网关,它在Istio安装的时候就被创建出来了。
让我们来创建网关。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: app-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
目的地规则
Istio目的地规则定义了流量被路由以后访问服务的规则。请注意在Kubernete中这个规则是如何利用标签来声明的。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: myapp
spec:
host: myapp
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
虚拟服务
虚拟服务定义了当主机获得地址以后一系列流量的路由规则。每一条路由规则都定义了某个基于特定协议的流量的匹配规则。当一个流量被匹配了,基于版本,它会被发送到相关的目标服务。
在下面的操作中,我们声明了V1和V2的权重都为50,这就意味着流量会被平均分配。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- "*"
gateways:
- app-gateway
http:
- route:
- destination:
host: myapp
subset: v1
weight: 50
- destination:
host: myapp
subset: v2
weight: 50
你可以把上面的YAML文件合成一个,同样可以用kubectl运行。你可以在GitHub Gist[2]找到相关的YAML文件。
$ kubectl apply -f app-gateway.yaml
现在我们来继续访问服务,既然我们用了Minikube和NodePort,我们需要知道Ingress网关到底运行在哪个端口。
运行下面的命令来访问Minikube和Ingress port。
$ export INGRESS_HOST=$(minikube ip)
$ export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
如果你能通过浏览器访问URL,你就能看到访问蓝色和绿色的流量是平均分配的。你也可以从终端看到结果。在终端运行下面的命令来看V1和V2的不同反馈。
while : ;do export GREP_COLOR='1;33';curl -s 192.168.99.100:31380 \
| grep --color=always "V1" ; export GREP_COLOR='1;36';\
curl -s 192.168.99.100:31380 \
| grep --color=always "vNext" ; sleep 1; done
上面的命令在循环运行,现在我们去更改app-gateway.yaml文件,把V1的权重改成0,V2的权重改成100。
提交这个新的配置给Istio。
$ istioctl replace -f app-gateway.yaml
当权重变化以后,100%的流量立即就路由到了V2。这个变化可以从第一个终端窗口看到。
你可以继续调整权重并观察流量被动态的重新路由,这些调整并没有产生任何服务终止。
流量管理只是Istio的特性之一。接下来的文章中,我们会继续探索Istio的其他功能。
相关链接:
https://gist.github.com/janakiramm/123dc67b78ef187a109e7f928d6a6878
https://gist.github.com/janakiramm/35078d95730745caa62f81d917d6d553
原文链接:https://thenewstack.io/tutorial-blue-green-deployments-with-kubernetes-and-istio/
Kubernetes线下实战培训
Kubernetes应用实战培训将于2018年12月21日在北京开课,3天时间带你系统学习Kubernetes
。本次培训包括:容器特性、镜像、网络;Docker特性、架构、组件、概念、Runtime;Docker安全;Docker实践;Kubernetes架构、核心组件、基本功能;Kubernetes设计理念、架构设计、基本功能、常用对象、设计原则;Kubernetes的实践、运行时、网络、插件已经落地经验;微服务架构、DevOps等,点击下方图片查看详情。