从docker到istio之四 - istio分流应用

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
传统型负载均衡 CLB,每月750个小时 15LCU
云数据库 Redis 版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 这是第四篇,istio分流应用。

image.png


前言



容器化,云原生越演越烈,新概念非常之多。信息爆炸的同时,带来层层迷雾。我尝试从扩容出发理解其脉路,经过实践探索,整理形成一个入门教程,包括下面四篇文章。



这是第四篇,istio分流应用。


istio



服务网格(Service Mesh)这个术语通常用于描述构成这些应用程序的微服务网络以及应用之间的交互。随着规模和复杂性的增长,服务网格越来越难以理解和管理。它的需求包括服务发现、负载均衡、故障恢复、指标收集和监控以及通常更加复杂的运维需求,例如 A/B 测试、金丝雀发布、限流、访问控制和端到端认证等。


Istio 提供了一个完整的解决方案,通过为整个服务网格提供行为洞察和操作控制来满足微服务应用程序的多样化需求。


安装istio


istio1.1支持kubernetes1.11,1.12,1.13,Docker for mac的stable版本太低,需要切换Docker for mac 到 edge版本,kubernetes会升级到1.13。使用 kubectl version 确认kubernetes版本:


Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", GitCommit:"ddf47ac13c1a9483ea035a79cd7c10005ff21a6d", GitTreeState:"clean", BuildDate:"2018-12-03T21:04:45Z", GoVersion:"go1.11.2", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", GitCommit:"ddf47ac13c1a9483ea035a79cd7c10005ff21a6d", GitTreeState:"clean", BuildDate:"2018-12-03T20:56:12Z", GoVersion:"go1.11.2", Compiler:"gc", Platform:"linux/amd64"}


按照安装指南安装istio到k8s。 kubectl get svc -n istio-system 查看isto服务(svc是service的速记别名)


NAME                     TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                                                                                                                                      AGE
grafana                  ClusterIP      10.96.238.84     <none>        3000/TCP                                                                                                                                     19s
istio-citadel            ClusterIP      10.110.233.235   <none>        8060/TCP,15014/TCP                                                                                                                           19s
istio-egressgateway      ClusterIP      10.107.81.184    <none>        80/TCP,443/TCP,15443/TCP                                                                                                                     20s
istio-galley             ClusterIP      10.108.48.185    <none>        443/TCP,15014/TCP,9901/TCP                                                                                                                   20s
istio-ingressgateway     LoadBalancer   10.99.64.197     localhost     15020:31681/TCP,80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:32145/TCP,15030:31376/TCP,15031:30092/TCP,15032:31491/TCP,15443:32689/TCP   19s
istio-pilot              ClusterIP      10.101.105.130   <none>        15010/TCP,15011/TCP,8080/TCP,15014/TCP                                                                                                       19s
istio-policy             ClusterIP      10.107.208.244   <none>        9091/TCP,15004/TCP,15014/TCP                                                                                                                 19s
istio-sidecar-injector   ClusterIP      10.104.152.19    <none>        443/TCP                                                                                                                                      19s
istio-telemetry          ClusterIP      10.102.233.77    <none>        9091/TCP,15004/TCP,15014/TCP,42422/TCP                                                                                                       19s
jaeger-agent             ClusterIP      None             <none>        5775/UDP,6831/UDP,6832/UDP                                                                                                                   18s
jaeger-collector         ClusterIP      10.100.208.250   <none>        14267/TCP,14268/TCP                                                                                                                          18s
jaeger-query             ClusterIP      10.104.246.180   <none>        16686/TCP                                                                                                                                    18s
kiali                    ClusterIP      10.100.34.9      <none>        20001/TCP                                                                                                                                    19s
prometheus               ClusterIP      10.103.238.247   <none>        9090/TCP                                                                                                                                     19s
tracing                  ClusterIP      10.103.49.38     <none>        80/TCP                                                                                                                                       18s
zipkin                   ClusterIP      10.105.126.70    <none>        9411/TCP


查看isto的pod是否全部正常启动:


➜  kubectl get pods -n istio-system
NAME                                      READY   STATUS      RESTARTS   AGE
grafana-749c78bcc5-jczt2                  1/1     Running     1          20m
istio-citadel-899dfb67c-r6cmx             1/1     Running     0          20m
istio-cleanup-secrets-1.1.3-d42jx         0/1     Completed   0          20m
istio-egressgateway-748d5fd794-zkcjs      1/1     Running     1          20m
istio-galley-555dd7c7d7-t9fhz             1/1     Running     0          20m
istio-grafana-post-install-1.1.3-2qzg5    0/1     Completed   0          20m
istio-ingressgateway-55dd86767f-n5v7m     1/1     Running     1          20m
istio-pilot-7979d58649-lg6vq              2/2     Running     0          20m
istio-policy-f89c945dc-8d6mn              2/2     Running     0          55s
istio-security-post-install-1.1.3-4ggpf   0/1     Completed   0          20m
istio-sidecar-injector-998dd6cbb-fbdgw    1/1     Running     0          20m
istio-telemetry-7d9d866c65-2pngr          2/2     Running     0          16s
istio-tracing-595796cf54-mp6tp            1/1     Running     1          20m
kiali-5df77dc9b6-jq26m                    1/1     Running     0          20m
prometheus-7f87866f5f-p2568               1/1     Running     0          20m


部署应用


调整pods符合istio规范


部署引用前,需要按照Istio对Pod和服务的要求,进行微调。


微调后的istio\flaskapp.yaml如下:


apiVersion: v1
kind: Service
metadata:
  name: flaskapp
spec:
  ports:
    - port: 5000
      name: http
  selector:
    app: business
---
apiVersion: extensions/v1beta1 
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: business
        version: v1
    spec:
      containers:
      - image: flaskapp:0.0.2
        name: flaskapp
        ports:
        - containerPort: 5000


微调后的istio\redis.yaml如下:


apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  ports:
    - port: 6379
      name: redis
  selector:
    app: redis
---
apiVersion: extensions/v1beta1 
kind: Deployment
metadata:
  name: redis
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: redis
        version: v1
    spec:
      containers:
      - image: redis:4-alpine3.8
        name: redisdb
        ports:
        - containerPort: 6379


因为istio附带ingress,所以我们取消了前置的nginx负载,直接使用ingress。


启动istio的sidecar自动注入


istio通过在pod中输入sidecar,用来管理流量,设置default名称空间下默认注入:


➜  docker2istio kubectl label namespace default istio-injection=enabled
namespace/default labeled


启动服务


启动服务方式和k8s没有区别


➜  docker2istio kubectl apply -f k8s/redis.yaml -f k8s/flaskapp.yaml
service/redis created
deployment.extensions/redis created
service/flaskapp created
deployment.extensions/flaskapp created


使用kubectl describe pod/flaskapp-757cd47df4-zkzv2 确认istio正常管理app:


Name:               flaskapp-757cd47df4-zkzv2
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               docker-desktop/192.168.65.3
Start Time:         Wed, 24 Apr 2019 18:43:16 +0800
Labels:             app=business
                    pod-template-hash=757cd47df4
                    version=v1
Annotations:        sidecar.istio.io/status:
                      {"version":"3420543c87a5049f8ec099530c3992a5c1f06bf54fa56d7a3877e7ffc658ea8d","initContainers":["istio-init"],"containers":["istio-proxy"]...
Status:             Running
IP:                 10.1.0.45
Controlled By:      ReplicaSet/flaskapp-757cd47df4
Init Containers:
  istio-init:
    Container ID:  docker://0bac5e70832c287a1c446d38034c75ebe5b8e66b9e2fb6d5a1fc3bcb8a9f644c
    Image:         docker.io/istio/proxy_init:1.1.3
    Image ID:      docker-pullable://istio/proxy_init@sha256:000d022d27c198faa6cc9b03d806482d08071e146423d6e9f81aa135499c4ed3
    Port:          <none>
    Host Port:     <none>
    Args:
      ...
Containers:
  flaskapp:
    Container ID:   docker://9cdf76e12c710f1d50c2b3a2ac349909f481975f220af5b31e1b76717bcabd95
    Image:          flaskapp:0.0.2
    Image ID:       docker://sha256:d52877069956696bb9009c0af43a0d339d2d253e67f5fb09c9f1f052a35528de
    Port:           5000/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Wed, 24 Apr 2019 18:43:19 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-ndv6q (ro)
  istio-proxy:
    Container ID:  docker://84eecd89d7c203b7b97749d2a02c63cb8b4c57cfda96f0c7585547a8918344c1
    Image:         docker.io/istio/proxyv2:1.1.3
    Image ID:      docker-pullable://istio/proxyv2@sha256:b682918f2f8fcca14b3a61bbd58f4118311eebc20799f24b72ceddc5cd749306
    Port:          15090/TCP
    Host Port:     0/TCP
    Args:
      ...
    State:          Running
      Started:      Wed, 24 Apr 2019 18:43:19 +0800
    Ready:          True
    Restart Count:  0
    Limits:
      cpu:     2
      memory:  128Mi
    Requests:
      cpu:      10m
      memory:   40Mi
    Readiness:  http-get http://:15020/healthz/ready delay=1s timeout=1s period=2s #success=1 #failure=30
    Environment:
      POD_NAME:                      flaskapp-757cd47df4-zkzv2 (v1:metadata.name)
      POD_NAMESPACE:                 default (v1:metadata.namespace)
      INSTANCE_IP:                    (v1:status.podIP)
      ISTIO_META_POD_NAME:           flaskapp-757cd47df4-zkzv2 (v1:metadata.name)
      ISTIO_META_CONFIG_NAMESPACE:   default (v1:metadata.namespace)
      ISTIO_META_INTERCEPTION_MODE:  REDIRECT
      ISTIO_METAJSON_LABELS:         {"app":"business","pod-template-hash":"757cd47df4","version":"v1"}
    Mounts:
      /etc/certs/ from istio-certs (ro)
      /etc/istio/proxy from istio-envoy (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-ndv6q (ro)
...


!!!注意 这里的pod,会被自动注入名为istio-init的initContainer和名为**istio-proxy的container。具有这2个container,标志pod接受istio流量管理。


确认服务正常启动


➜  docker2istio kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
flaskapp     ClusterIP   10.107.67.44     <none>        5000/TCP       4m31s
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        36m
redis        ClusterIP   10.100.210.72    <none>        6379/TCP       4m31s


确认pod正常启动


➜  docker2istio kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
flaskapp-77ddb9698c-xb2gm   1/1     Running   0          4m2s
redis-c5dd6fcfc-8tqwm       1/1     Running   0          4m2s


部署istio的gateway


因为取消了前置的nginx负载,需要设置gateway,集群外部才能够访问服务。istio\gateway.yaml:


apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: flaskapp-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: flaskapp
spec:
  hosts:
  - "*"
  gateways:
  - flaskapp-gateway
  http:
  - match:
    - uri:
        exact: /
    route:
    - destination:
        host: flaskapp
        port:
          number: 5000


kubectl apply -f istio/gateway.yaml提交后,查看gameway的端口:


➜  docker2istio kubectl get svc istio-ingressgateway -n istio-system
NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                                                                                                                      AGE
istio-ingressgateway   LoadBalancer   10.99.64.197   localhost     15020:31681/TCP,80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:32145/TCP,15030:31376/TCP,15031:30092/TCP,15032:31491/TCP,15443:32689/TCP   179m


这里的服务类型为LoadBalancer,可以直接使用80端口访问服务:



➜  docker2istio curl http://localhost
Hello World by 10.1.0.40 from 10.1.0.30 ! 该页面已被访问 1 次。


金丝雀发布



istio的流量管理提供了非常便捷的金丝雀发布功能。


首先,我们调整app/flaskapp.py,将域名获取调整成为主机名称:


#-*- coding:utf-8 -*-
import socket
from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
def get_host_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.connect(('8.8.8.8', 80))
        ip = s.getsockname()[0]
    except:
        ip = '127.0.0.1'
    finally:
        s.close()
    return ip
def get_hostname():
    return socket.gethostname()
@app.route('/')
def hello():
    app.logger.debug('hello in')
    from flask import request
    count = redis.incr('hits')
    # host_ip = get_host_ip()
    host_id = get_hostname()
    client_ip= request.headers['X-Real-Ip'] if 'X-Real-Ip' in request.headers else request.remote_addr 
    app.logger.debug("Hello out {} {} {}:".format(host_id,client_ip,count))
    return 'Hello World by {} from {} ! 该页面已被访问 {} 次。\n'.format(host_id,client_ip,count)
if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)


使用 docker build -f app/Dockerfile -t flaskapp:0.0.3 app 编译新的镜像。


制作新的deployment,使其使用新的镜像:


apiVersion: extensions/v1beta1 
kind: Deployment
metadata:
  name: flaskapp-v2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: business
        version: v2
    spec:
      containers:
      - image: flaskapp:0.0.3
        name: flaskapp
        ports:
        - containerPort: 5000


创建并确认新的部署生效:


➜  docker2istio kubectl apply -f istio/flaskappv2.yaml
deployment.extensions/flaskapp-v2 created
➜  docker2istio kubectl get deployment
NAME          READY   UP-TO-DATE   AVAILABLE   AGE
flaskapp      3/3     3            3           72m
flaskapp-v2   1/1     1            1           7s
redis         1/1     1            1           129m


调整VirtualService,控制流量分发策略:


apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: flaskapp
spec:
  hosts:
  - "*"
  gateways:
  - flaskapp-gateway
  http:
  - match:
    - uri:
        exact: /
    route:
    - destination:
        host: flaskapp
        port:
          number: 5000
  - route:
    - destination:
        host: flaskapp
        subset: v1
      weight: 80
    - destination:
        host: flaskapp
        subset: v2
      weight: 20


这里重点是指定规则,按照8:2,将flaskapp的访问分配到deployment v1 和 deployment v2 上。


kubectl apply -f istio/gateway2.yaml 应用新的流量分配策略:


访问观察服务:


➜  docker2istio curl http://localhost
Hello World by 10.1.0.45 from 127.0.0.1 ! 该页面已被访问 7 次。
➜  docker2istio curl http://localhost
Hello World by 10.1.0.45 from 127.0.0.1 ! 该页面已被访问 8 次。
➜  docker2istio curl http://localhost
Hello World by flaskapp-v2-ff9f8cfdb-vh788 from 127.0.0.1 ! 该页面已被访问 9 次。
➜  docker2istio curl http://localhost
Hello World by 10.1.0.45 from 127.0.0.1 ! 该页面已被访问 10 次。
➜  docker2istio curl http://localhost
Hello World by 10.1.0.45 from 127.0.0.1 ! 该页面已被访问 11 次。
➜  docker2istio curl http://localhost
Hello World by 10.1.0.45 from 127.0.0.1 ! 该页面已被访问 12 次。
➜  docker2istio curl http://localhost
Hello World by 10.1.0.45 from 127.0.0.1 ! 该页面已被访问 13 次。
➜  docker2istio curl http://localhost
Hello World by flaskapp-v2-ff9f8cfdb-vh788 from 127.0.0.1 ! 该页面已被访问 14 次。


可以看到,访问被按比例分配到v1和v2两个版本上。


总结



从上面实践过程空可见,istio完善了k8s提供的编排功能,在纵向扩容的基础上可以实现横向扩展。


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
7天前
|
弹性计算 运维 持续交付
探索Docker容器化技术及其在生产环境中的应用
探索Docker容器化技术及其在生产环境中的应用
38 5
|
8天前
|
Cloud Native 持续交付 Docker
探索Docker容器化技术及其在软件开发中的应用
探索Docker容器化技术及其在软件开发中的应用
17 7
|
6天前
|
Devops jenkins 持续交付
DevOps实践:构建和部署一个Docker化的应用
【9月更文挑战第14天】在当今快节奏的软件开发领域,DevOps已经成为提升效率、加速交付的关键。本文将引导你理解DevOps的核心概念,并通过一个实际的示例—构建和部署一个Docker化的应用—来深入探讨其实践方法。我们将从简单的应用出发,逐步实现Docker容器化,并最终通过CI/CD流水线自动化部署过程。这不仅是对DevOps流程的一次实操演练,也是对现代软件开发理念的一次深刻体验。
|
10天前
|
持续交付 开发者 Docker
掌握 Docker:容器化技术在现代开发中的应用
Docker 是一个开源容器化平台,使开发者能够将应用程序及其依赖项封装在轻量级容器中,确保跨平台的一致性。本文介绍了 Docker 的基本概念、核心组件及优势,并展示了其在快速部署、一致性、可移植性和微服务架构中的应用。通过示例说明了 Docker 在本地开发环境搭建、服务依赖管理和 CI/CD 流程中的作用,以及多阶段构建、资源限制和网络模式等高级特性。掌握 Docker 可大幅提升开发效率和应用管理能力。
|
16天前
|
负载均衡 持续交付 Docker
Docker的应用场景有哪些?
Docker的应用场景有哪些?
48 6
|
16天前
|
负载均衡 大数据 测试技术
docker容器技术有哪些应用场景?
docker容器技术有哪些应用场景?
31 5
|
20天前
|
容器 C# Docker
WPF与容器技术的碰撞:手把手教你Docker化WPF应用,实现跨环境一致性的开发与部署
【8月更文挑战第31天】容器技术简化了软件开发、测试和部署流程,尤其对Windows Presentation Foundation(WPF)应用程序而言,利用Docker能显著提升其可移植性和可维护性。本文通过具体示例代码,详细介绍了如何将WPF应用Docker化的过程,包括创建Dockerfile及构建和运行Docker镜像的步骤。借助容器技术,WPF应用能在任何支持Docker的环境下一致运行,极大地提升了开发效率和部署灵活性。
35 0
|
20天前
|
C# 开发者 Windows
WPF与PDF文档:解锁创建和编辑PDF文件的新技能——从环境配置到代码实践,手把手教你如何在WPF应用中高效处理PDF,提升文档管理效率
【8月更文挑战第31天】随着数字文档的普及,PDF因跨平台兼容性和高保真度成为重要格式。WPF虽不直接支持PDF处理,但借助第三方库(如iTextSharp)可在WPF应用中实现PDF的创建与编辑。本文通过具体案例和示例代码,详细介绍了如何在WPF中集成PDF库,并展示了从设计用户界面到实现PDF创建与编辑的完整流程。不仅包括创建新文档的基本步骤,还涉及在现有PDF中添加页眉页脚等高级功能。通过这些示例,WPF开发者可以更好地掌握PDF处理技术,提升应用程序的功能性和实用性。
36 0
|
20天前
|
应用服务中间件 Java Maven
掌控视图的力量!深入解析 JSF 视图管理,揭秘视图生命周期的秘密,让你的应用更高效!
【8月更文挑战第31天】JavaServer Faces (JSF) 是一种强大的框架,用于管理 Web 应用程序的视图。本文通过具体案例介绍 JSF 视图管理的基础知识,包括创建、管理和销毁视图的过程。首先,在 Eclipse 中创建一个新 JSF 项目,并配置 Maven 依赖。接着,在 `WEB-INF` 目录下配置 `web.xml` 文件,设置 JSF servlet。
31 0
|
20天前
|
JavaScript 应用服务中间件 nginx
玩转现代化部署:Angular与Docker的完美邂逅——细说如何通过容器化技术让您的Angular应用飞速上线,实现一键部署的高效与便捷,彻底告别复杂流程
【8月更文挑战第31天】容器化技术已成现代软件部署标配,为应用提供一致的运行环境。本文通过具体示例详细介绍了如何使用 Docker 容器化 Angular 应用,包括创建 Angular 项目、编写 Dockerfile 以及构建和运行 Docker 镜像的过程,显著提升了部署效率与可靠性。无论在本地调试还是生产部署,Docker 均提供了高效解决方案。
34 0