使用Kubernetes和Istio实现蓝绿部署

18-10-22 banq
              

Istio是一种服务网格,使微服务之间的通信可靠,透明和安全。Istio拦截Kubernetes中部署的服务访问。

尽管Istio能够执行许多操作,包括服务到服务通信、指标的自动记录、实施访问控制策略,速率限制和配额,但我们这里讲专注于流量管理功能。

Istio允许DevOps团队创建规则,智能地将流量路由到内部服务。配置服务级属性(如断路器,超时和重试)非常简单,可以设置各种部署模式,包括蓝/绿部署和金丝雀部署。

本教程的目的是帮助您了解如何使用Istio配置在Kubernetes中运行的微服务的蓝/绿部署。除了在Kubernetes中部署pod和服务的基本思想之外,你无需具备探索此方案的任何先决条件。我们将配置从Minikube到Istio的所有内容到示例应用程序。

本教程分为四个步骤 :

1. 安装Minikube,

2. 安装和验证Istio

3. 部署同一应用程序的两个版本,

4. 最后配置蓝/绿部署服务。

我们将使用两个简单的预先构建的容器镜像来表示蓝色(V1)和绿色(V2)版本。

第1步:安装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

我们需要至少8GB的RAM和4核CPU才能在Minikube上运行Istio。等待群集启动。。。

第2步:安装Istio

随着Kubernetes的启动和运行,现在是我们安装Istio的时候了。请按照以下步骤进行配置。

$ curl -L https://git.io/getLatestIstio | sh -

在运行上述命令的同一目录中找到一个文件夹istio-1.0.2。将位置istio-1.0.2 / bin添加到PATH变量,以便于访问Istio二进制文件。

由于我们使用Minikube运行Istio,我们需要进行一次更改,然后再继续下一步 - 将Ingress Gateway服务从LoadBalancer类型更改为NodePort。

打开文件istio-1.0.2 / install / kubernetes / istio-demo.yaml,搜索LoadBalancer并将其替换为NodePort。 Istio为Kubernetes提供了许多自定义资源定义(CRD)。它们帮助我们从kubectl操纵虚拟服务,规则,网关和其他特定于Istio的对象。让我们在部署实际服务网格之前安装CRD。

$ kubectl apply -f install/kubernetes/helm/istio/templates/crds.yaml

最后,让我们在Kubernetes中安装Istio。

$ kubectl apply -f install/kubernetes/istio-demo.yaml

上面的步骤导致创建一个新的命名空间 - istio-system - 在其下部署多个对象。

通过kubectl get ns能够查询到。

几分钟后,您将看到Istio部署的多个pod。通过运行kubectl get pods -n = istio-system验证这一点

所有pod必须处于运行或完整模式,这表示已成功安装和配置Istio。

现在,我们已准备好为蓝/绿模式部署和配置服务。

第3步:部署同一应用程序的两个版本

为了表示两个不同版本的应用程序,我构建了简单的基于Nginx的Docker镜像 - janakiramm /myapp:v1和janakiramm/myapp:v2。部署后,它们会显示带有蓝色或绿色背景的静态页面。我们将使用这些图像作为教程。

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

上面配置文件在:gist

让我们首先创建一个YAML文件,该文件定义V1和V2的部署以及公开它们的ClusterIP。请注意用于标识pod的标签labels格式是需要 app和version两个字段。虽然应用名称保持不变,但两个部署之间的版本不同。

Istio希望将它们视为单个应用程序,但要根据版本区分它们。

ClusterIP服务定义也是如此。labels标签app:myapp与基于不同版本的两个部署中的pod相关联。

  labels:
        app: myapp
        version: v1或v2 这里版本不同

使用下面kubectl命令创建部署和服务。请注意,这些是简单的Kubernetes对象,它们不知道Istio是否存在,它们与Istio的唯一连接是我们为其部署和服务创建标签的方式。

$ kubectl apply -f myapp.yaml

在配置Istio路由之前,让我们看看我们的应用程序的版本。

要访问应用程序的V1版本,请运行以下命令并点击localhost:8080。完成后按CTRL + C.

$ kubectl port-forward deployment/myapp-v1 8080:80

对于V2,运行以下命令并点击localhost:8081。完成后按CTRL + C.

$ kubectl port-forward deployment/myapp-v2 8081:80

第4步:配置蓝/绿部署

我们的目标是在没有停机的情况下有选择地将流量驱动到其中一个部署。为实现这一目标,我们需要告诉Istio根据权重来路由流量。

实现这一目标涉及三个对象:

1.Gateway

Antio Gateway描述了在网格边缘操作的负载均衡器,用于接收传入或传出的HTTP / TCP连接。规范描述了应该公开的一组端口,要使用的协议类型,负载均衡器的SNI配置等。在下面的定义中,我们将网关指向安装期间由Istio创建的默认Ingress Gateway。

让我们将网关创建为Kubernetes对象。

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文件以Github Gist的形式提供

$ kubectl apply -f app-gateway.yaml

现在,让我们继续访问该服务。由于我们将Minikube与NodePort一起使用,因此我们需要获得运行Ingress Gateway的确切端口。

运行以下命令以访问Ingress主机(Minikube)和Ingress端口。

$ export INGRESS_HOST=$(minikube ip)

$ export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')

如果您从浏览器访问URI,您将看到在蓝色和绿色页面之间均匀路由的流量。

我们可以从终端窗口看到结果。从终端窗口运行以下命令,查看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

您可以继续调整权重并观察动态重新路由的流量,不会导致任何停机。