云原生架构和Kubernetes容器云部署

Posted by WZhong on Tuesday, January 21, 2020

TOC

到底什么是云原生架构

  1. 云原生应用定义

    • 软件开发行业,早前从XP(ExtremeProgramming)极限编程、敏捷Agile、DevOps等,没有明确定义,是业界最佳实践的一些统称
    • Applications adoptiong the principles of Microservices packaged as Containers orchestracted by Platforms running on top of Cloud infrastructure, developed using practices such as Continous Delivery and DevOps.
    • 基于微服务原理开发的应用,以容器方式打包;在运行时,容器由运行于云基础设施之上的平台进行调度;应用开发采用持续交付和DevOps实践
  2. 云演进史

    • Non-Virtualized:企业计算一般直接采用硬件服务器,如sun提供的中高端企业计算服务器
    • Virtualization:可以用软件方式按需创建虚拟机
    • IaaS(Infrastructure as a Service):基础设施即服务,把计算、网络、存储封装成可以按需使用的资源,amazon将其商业化,退出了AWS公有云
    • PaaS(Platform as a Service):平台即服务,比IaaS的抽象层次更高,IaaS主要面向计算、网络、存储这些计算资源,PaaS是一个应用的运行时平台,用户在PaaS平台上可直接部署应用,不需要关心底层的计算资源;HEROKU可认为是现代云原生平台的鼻祖或原型
    • Open Souce IaaS:开源IaaS产品,标志性的就是Openstack,它满足中大型企业自建私有云的需求
    • Open Souce PaaS:开源PaaS产品,标志性的就是Cloud Foundry,后被Pivotal收购
    • Containers:颠覆式的Docker容器技术出现,从开始就走开源路线,使得容器技术在行业内快速普及
    • Cloud Native:随着Docker和K8s的快速普及,大厂开始了立标准的过程,成立了CNCF组织,专门推动云原生项目的治理、推广和应用,标志着计算进入了云原生时代
    2000 2001 2006 2009 2010 2011 2013 2015
    Sun vmware amazon HEROKU openstack CLOUD FOUNDRY docker CLOUD NATIVE
    Non-Virtualized Hardware Virtualization IaaS PaaS Open Source IaaS Open Source PaaS Containers Cloud Native
  3. CNCF - Cloud Native Computing Foundation

Kubernetes背景和架构

  1. Kubernetes历史

    • 支持云原生应用的一个平台,起源于google,每周要启动20亿个容器
    • google的容器平台发展:
      • 第一代:Borg,内部产品,2003~2004,经典的master-slave架构;master提供api,cli、ui、外部系统通过api跟集群交互;每个slave节点安装一个Borglet的组件,用于管理容器、网络、路由;调度程序scheduler根据slave上的资源使用情况进行调度决策,并且指挥Borglet进行操作
      • 第二代:Omega,是Borg的升级版
      • 第三代:开源的Kubernetes,古希腊的词语,意为船长、舵手;专门用来指挥调度容器;
  2. Kubernetes趋势

    • 稳步上升,项目提交数量活跃
  3. Kubernetes解决什么问题:

    • 本质上简化微服务的开发和部署,解决微服务的公共关注点
    • DevOps开发者体验 / 微服务 / IaaS(操作系统,虚拟化,硬件/网络/存储)
    • K8s解决微服务中的:
      • 服务发现和LB
      • 弹性和容错
      • API管理
      • 服务安全
      • 日志监控
      • Metrics监控
      • 调用链监控
      • 调度和发布
      • 自愈和自动伸缩
    • 和Dubbo、Spring Cloud相比,K8s是解决微服务公共关注点最全面的一个平台性的解决方案;K8s对公共关注点大部分以组件形式封装打包到K8s大平台中,让开发人员在开发微服务时专注业务逻辑的实现,不需要特别关注微服务底层的公共关注点
  4. Kubernetes架构:经典的Master-Slave架构

    • Master Nodes 和 Worker Nodes,可以是物理机或虚拟机
    • Master节点:
      • etcd:基于K-V的分布式存储机制,底层采用raft协议;K8s集群的状态数据,包括配置、节点、Pod等等,最终都存储在etcd中
      • API server:对外提供操作和获取k8s集群资源的api,是唯一操作etcd的组件,可以简单理解为是etcd的代理
      • Scheduler:相当于k8s的大脑,负责调度决策,如对新的应用发布请求,schduler负责决策响应的pods应该分布在哪些worker节点上
      • Controller Manager:相当于集群状态的协调者,观察目前集群的实际状态,和etcd中的预期状态进行比对,不一致的话就要对资源进行协调操作,让实际状态和预期状态达到最终一致;所有k8s采用一种最终一致调度机制,支持自愈,只要etcd中的预期数据还在,k8s就能最终恢复到预期状态
      • 为保证高可用,master节点一般采用多节点部署,但是真正做调度决策的只有一个master节点,所以有一个选主leader election的动作;如果主master节点挂了,其他节点会再选主节点;
      • etcd集群一半是单独部署
    • Worker节点
      • Container Runttime:下载镜像和运行容器的组件;如果采用docker,那么每个节点上都会运行一个docker daemon,运行容器时,如果本地没有镜像,那么daemon就会从docker registry抓取响应镜像
      • Pod:简单理解为对容器的包装,是K8s的基本调度单位;实际的容器是运行在pod中的;一个节点上可以启动一个或多个pod,一个应用的pods也可分布在一个或多个节点上;pod之间进行通讯是通过内部的overlay network
      • kubelet:负责管理worker节点上的组件,相当于一个agent角色;和master节点的API server进行交互,接收指令执行操作,如启动pod、关闭pod,也返回一些状态数据或事件到master;是每个worker节点上的小脑
      • kube-proxy:负责对pod进行寻址和负载均衡;是实现service和服务发现抽象的关键;底层操作iptable规则
    • 用户操作k8s集群,一般是通过kubectl命令行工具或k8s的dashboard访问k8s集群,这些工具都通过API server与集群进行交互;外部流量进入k8s去访问pod一般是通过Load Balancer设备
    • K8s外围还有一些存储、监控、日志、分析这些配套的服务
    • 架构复杂、重量,中小企业不建议自建集群,而采用公有云k8s集群

Kubernetes有哪些基本概念

  1. 集群 Cluster

    • 很多节点组成,可以按需添加更多节点,节点可以是物理机,也可以是虚拟机
    • 每个节点都有CPU和内存
    • 整个集群可看作一个超大的计算机
  2. 容器 Container

    • 从宿主机操作系统的视角看,容器是一个一个的进程
    • 从容器内部的视角看,容器是一个一个完整的操作系统,文件系统、网络、CPU、Memory等完整的资源
  3. POD

    • K8s并没有直接调度容器,而是在容器外层封装了一个叫Pod的概念:原因一是考虑一些需要辅助容器的场景,如有些需要sidecar的场景;原因二是考虑可以替换使用不同的容器技术
    • POD是k8s的基本调度单位
    • 一个Pod内可以跑一个或多个容器,共享该pod的文件系统和网络,每个pod有独立的ip,pod中的容器共享这个ip和端口空间;并且同一个pod中的容器可通过localhost相互访问
    • 大部分场景下一个pod只跑一个应用容器
  4. 副本集 ReplicaSet

    • 一个应用发布的时候一般不会只发一个pod实例,而是会发多个pod实例,这样才能实现高可用;ReplicaSet就是和一个应用的一组pod相对应的概念,可通过模板yaml或json来规范某个应用的容器镜像、端口、副本数量、点火和健康检查机制、环境变量、volume挂载等相关信息
    • 运行时,ReplicaSet会监控和维护pod的数量,过多则下线pod,过少会启动pod
  5. 服务 Service

    • pod在k8s中是一个ephemeral(短暂的、无常的事物)的,可能会随时挂或重启,响应ip会发生变化,如果一个服务的实例ip不固定,服务的消费者无法寻址
    • k8s通过引入service这样的抽象概念来解决:简单来讲,service屏蔽了应用的ip寻址和负载均衡这些小细节,消费方可以直接通过服务名访问目标服务;k8s中的service底层机制会做寻址和负载均衡,即使应用的pod的ip发生变更,service也会屏蔽这种变更,让消费方无感知
  6. 发布 Deployment

    • 副本集可认为是一种基本的发布机制,但是操作起来繁琐,为了简化高级的发布,在ReplicaSet的基础上,引入了Deployment概念
    • 简单讲,Deployment是用来管理ReplicaSet,实现蓝绿和滚动这些高级发布机制
    • 通过Deployment调度实现滚动发布(Rolling Update)的样例
      • 假设应用的1.0绿色版本已发布,对应的ReplicaSet是v1.0,通过Deployment进行升级发布应用的1.1蓝色版本,Deployment就会创建ReplicaSet v1.1,之后Deployment会依次调度:不断拉入蓝色版本,拉出绿色版本,直到所有的蓝色pod全部上线,绿色pod全部下线;过程中service抽象会屏蔽应用地址的变更,让消费方无感知;如果在滚动发布的过程中,蓝色pod有问题,如点火健康检查通不过,delployment会自动终止并回退发布;即使发布成功完成,后续如果根据需要,仍可通过deployment回退到之前发布的某个版本
    • 发布和服务总结
      • Deployment和Service是和微服务发布相关最重要的两个概念,也是发布过程中经常要使用的两个概念
      • 发布微服务时所书写定义的描述文件里面主要就是Deployment和Service的规范
  7. ConfigMap/Secret

    • 微服务在上线的时候需要设置一些可变配置,针对不同环境对应的设定值不同;这些配置有些是在启动期一次配置完成的,如数据库连接字符串,还有一些配置是在运行期可动态调整的,如缓存过期时间、TTL值、业务促销的商品限购数量等;所以微服务需要配置中心的支持,实现针对不同环境的灵活的动态配置
    • K8s内置支持微服务的配置,对应概念叫ConfigMap,是K8s平台支持的一种资源,开发人员将配置填写在ConfigMap中,K8s将ConfigMap中的配置以环境变量的形式注入到pod中,这样pod中的应用可以以环境变量的形式去访问这些配置
    • ConfigMap也支持以持久卷Volume的形式mount到Pod中,这样pod的应用以本地配置文件的形式来访问配置
    • k8s通过Secret来支持敏感数据的配置,可认为是一种特殊的Config,提供更安全的存储和访问配置的机制
  8. DaemonSet

    • 一种常见场景:需要在每个节点上常驻一个守护进程,如监控场景需要在每个机器上部署一个fluentD日志采集进程或Prometheus的exporter进程
    • K8s针对这样的场景,k8s支持一个叫DaemonSet这样一个概念,可以在每个worker节点上面部署一个守护进程pod,并且保证每个节点上有且仅有这样的一个pod
  9. 其他概念

    • Volume:存储卷抽象,简单可理解为磁盘文件存储,可以是节点本地文件存储,也可是远程存储;挂载mount之后,volume成为pod的一部分,pod销毁volumen也会销毁,但是支持volume的存储可以还在

    • PersistentVolume:持久卷,如果volume只用节点文件的本地存储,那么下次应用容器重启可能会换一个节点,响应的文件存储就不存在了;持久卷是一种高级的存储资源抽象,可对接各种云存储,由集群管理员统一配置

    • PersistentVolumeClaims:应用申请PV时需要填写的规范,包括磁盘大小、类型等等;应用通过PVC申请PV资源,然后以Volume的形式挂载到pod当中;PV和PVC的引入使得Volume和具体的物理存储可进一步的解耦

    • POD -> Volume -> PVC -> PV -> 物理存储

    • StatefulSet:支持有状态应用的一种发布机制,如发布mysql数据库或redis缓存需要StatefulSet,和ReplicaSet相对应

    • Job:支持跑一次的任务

    • CronJob:支持周期性任务

  10. 概念补充

    • Label/Selector

      • Label是给k8s中的资源打标签的一种机制,如在pod上打标签标识该pod是属于后端还是前端、是生产的还是staging的、版本信息等;Selector是通过标签查询定位资源的一种机制
    • Namespace

      • k8s中的一种逻辑性隔离机制,基于namespace可以实现诸如多租户、环境、项目、团队这些逻辑隔离;还可以限制配额quota,创建资源时如果没有指定namespace,那么创建的资源都会住在缺省的namespace中
    • Readiness Probe(就绪探针)

      • 用于判断pod是否可以接入流量,如通过应用的health健康检查端点可以检查这个pod是否就绪,就绪的话就可以接入流量,否则不可以接入流量
    • Liveness Probe(活跃探针)

      • 用于判断pod是否存活,如通过应用的health健康检查端点可以定期检查这个pod是否存活,不存活就kill掉这个pod,并根据配置的策略决定是否要重启这个pod
  11. 概念总结

概念 作用
Cluster 超大计算机抽象,由节点组成
Container 应用居住和运行在容器中
Pod Kubernetes基本调度单位
ReplicaSet 创建和管理Pod,支持无状态应用
Service 应用Pods的访问点,屏蔽IP寻址和负载均衡
Deployment 管理ReplicaSet,支持滚动等高级发布机制
ConfigMap/Secrets 应用配置,secret敏感数据配置
DaemonSet 保证每个节点有且仅有一个Pod,常见于监控
StatefulSet 类似ReplicaSet,但支持有状态应用
Job 运行一次就结束的任务
CronJob 周期性运行的任务
Volume 可装载磁盘文件存储
PersisentVolumne/PersistentVolumeClaims 超大磁盘存储抽象和分配机制
Label/Selector 资源打标签和定位机制
Namespace 资源逻辑隔离机制
Readiness Probe 就绪探针,流量接入Pod判断依据
Liveness Probe 存活探针,是否kill pod的判断依据

理解Kubernetes节点网络和Pod网络

  1. 节点网络

    • K8s最底层的网络,用来保证k8s集群的节点(包括master和worker节点之间、worker节点之间)能够正常做ip寻址和通讯
  2. Pod网络

深入理解Service和Service Discovery

  1. Service如何寻址

  2. 用户空间代理模式

  3. iptables/ipvs模式

NodePort vs. LoadBalancer vs. Ingress

  1. 外部流量如何对Service寻址

  2. NodePort

  3. Load Balancer

  4. Ingress

  5. 总结

本地测试Kubernetes部署文件剖析

  1. 本地Kubernetes部署架构
    • 与docker-compose相比,增加mysql-svc
      • DB与k8s在两个不同的网络,通过mysql-svc间接去访问db
    • faraday网关需要向外暴露端口
      • 在本机,如果要把k8s内部的服务暴露,采用NodePort方式30001:80
      • 通过端口转发将faraday网关再暴露80:80
  2. 部署文件剖析 staffjoy-master/k8s/
    • test/config/config.yaml
      • 私密数据单独放置
      • 使用kide: ConfigMap形式,使k8s管理配置
    • test/mysql-svc.yaml
      • 使用kind: Service创建mysql服务
      • ip地址和端口
    • test/account-svc.yaml
      • 定义kind: Deployment用于发布,底层管理replicaset,管理pod
      • 定义kind: Service用于屏蔽pod ip,用于做负载均衡

本地测试Kubernetes环境搭建

  1. Docker Desktop for Mac/Win

  2. 校验Kubernetes

    • 查看版本

      kubectl version

    • 查看当前context

      kubectl config current-context

    • 查看集群信息

      kubectl cluster-info

    • 查看nodes

      kubectl get nodes

  3. 安装和访问Kubernetes Dashboard

    • 安装kubernetes dashboard https://github.com/kubernetes/dashboard

      kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc1/aio/deploy/recommended.yaml

      kubectl create -f kubernetes-dashboard.yaml

      通过查看pod检查dashboard是否安装好,需指定namespace为kube-system

      kubectl get pods --namespace=kube-system

    • 启动kube proxy

      kubectl proxy

    • 生成访问令牌

      kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')

      $TOKEN=((kubectl -n kube-system describe secret default | Select-String "token:") -split " +")[1]

    • 访问dashboard

将staffjoy部署到本地Kubernetes环境

  1. 构建镜像

    mvn clean package -DskipTests

    docker-compose build

    docker images

  2. 部署数据库,授予ip访问权限

    use mysql;
    select user, host from user;
    grant all privileges on *.* to root@192.168.1.38 identified by 'root' with grant option;
    
  3. 部署staffjoy(k8s/test),k8s dashboard查看nodes、pods、config maps、services

    kubectl apply -f config.yml

    kubectl get configmaps

    kubectl apply -f test

  4. 端口转发:因为在本地通过NodePort把faraday网关暴露出来,但NodePort是30001端口,如果要用域名方式访问本地微服务要求端口是80,所以需要将faraday的80端口转发到主机上的80

    • 查询faraday的pod名

    kubectl get pods

    • 端口转发

    kubectl port-forward faraday-svc-deployment-6f8f7ff9b7-rgqm4 80:80

  5. 启用switchhosts

  6. 命令行校验

    kubectl get pods -o wide

    kubectl get services

    kubectl get deployments

  7. k8s dashboard校验

    • 查看nodes、pods、config maps、services
  8. staffjoy校验

  9. 清理

    kubectl delete deployments --all

    kubectl delete services --all

    kubectl delete configmaps --all

生产环境Kubernetes部署文件剖析

  1. Staffjoy阿里云Kubernetes部署架构

    • 阿里云k8s住在aliyun VPC(虚拟私有云)中
      • VPC隔离性较好,生产环境一般都住在VPC中
    • 数据库使用aliyun RDS(关系型数据库服务)
      • 生产环境一般用云提供的数据库
    • 使用aliyun ELB(弹性负载均衡)来暴露微服务应用
      • 可通过ELB提供的ip访问微服务应用
  2. 阿里云Kubernetes拓扑结构

  3. 部署文件 staffjoy-master/k8s/uat

阿里云Kubernetes环境创建

  1. 创建VPC

    • https://homenew.console.aliyun.com
    • 专有网络VPC -> 选区域 -> 创建专有网络
      • 专有网络:名称staffjoy-k8s-vpc,IPv4网段默认,资源组默认
      • 交换机:名称staffjoy-k8s-switch001,可用区B,IPv4网段192.168.1.0/24
  2. 创建RDS

    • RDS管理控制台 -> 创建实例 -> 按量付费
      • 地域与VPC相同,资源组默认,数据库MySQL,版本5.7,系列基础版,存储类型SSD云盘,可用区与VPC可用区相同,网络类型专有网络,规格2核4G,存储空间150G,立即购买,支付(0.65元/时)
      • 管理控制台 -> 点击实例名称进行设置
    • 设置白名单,添加白名单分组
      • 选专有网络,分组名称staffjoy_rds,组内白名单192.168.1.0/24,确定
      • 复制内网地址
    • 更新JDBC连接字符串
      • 更新config.yaml文件中的连接字符串中的连接、账户、密码
    • 创建root账户
      • 账号管理,创建帐号
      • 数据库帐号root,密码Root1234
    • 创建数据库和表
      • 登录数据库,root,Root1234;设置所有实例
      • 数据库管理;创建数据库:数据库名staffjoy_account,确定;创建数据库:数据库名staffjoy_company,确定
      • SQL操作,SQL窗口,执行建表语句
  3. 创建共享版Kubernetes集群

    • 容器服务Kubernetes版,创建Kubernetes集群,标准托管集群
      • 集群名称staffjoy-k8s-cluster,地域一致,专有网络如前VPC,虚拟交换机选中,Worker实例新增实例,节点类型按量付费,实例规格4核8G,数量3台,系统盘SSD云盘120GB,Kubernetes版本1.12.6-aliyun.1,操作系统Linux,网络插件Flannel,Pod网络CIDR 172.20.0.0/16,Service CIDR 172.21.0.0/20,配置SNAT 为专有网络配置SNAT,公网访问 使用EIP暴露API Server,Ingress不需要选中,RDS白名单添加
    • 更新 .kube/config(配置context,使用本地kubectl指向阿里云kubernetes)
      • 点击集群名称,KubeConfig(公网访问),复制到$HOME/.kube/config
      • 复制 -cluster,添加到目标文件
      • 复制 -context到current-context,替换目标文件响应内容
      • 复制 -name,添加到目标文件
  4. 校验

    • kubectl config current-context
    • kubectl cluster-info
    • kubectl get nodes

将staffjoy部署到阿里云Kubernetes环境

  1. 部署staffjoy(k8s/UAT)

    • 部署config.yaml和logback-config.yaml

    kubectl apply -f config

    • 部署service和deployment

    kubectl apply -f uat

  2. 阿里云dashboard校验

    • 容器服务Kubernetes版,集群的控制台
    • 注意:微服务的镜像要docker-compose push到docker hub
    • 查看pod、logs
    • 查看config maps:common-config,logback-config
  3. 命令行校验

    kubectl get pods -o wide

    kubectl get services

    kubectl get deployments

  4. 更新并启用SwitchHosts

    • 获取faraday公网ip
    • 更新ELB IP地址
  5. staffjoy校验

  6. 删除阿里云kubernetes和RDS

Kubernetes应用动态配置实验

  1. k8s dashboard校验

    • 进入account-svc的pod命令控制台
    • /etc/staffjoy下有logback-spring.xml(这是发布uat环境时,把logback以configMap的形式mount到了pod里面)
    • 校验logback-spring.xml文件内容
      • scanPeriod为配置刷新时间间隔
      • level为日志级别
  2. 更新logback配置(k8s/UAT/config)

    • 更新logback-config.yaml中的level为debug
    • kubectl apply -f logback-config.yaml
  3. k8s dashboard校验

    • account-svc的pod命令控制台,校验logback-spring.xml文件更新
    • 等待30秒
    • account-svc的pod日志控制台输出debug日志

Kubernetes应用金丝雀发布实验

  1. 金丝雀发布

    • 假设线上有一个v1版本,现在有一个v2版本需要更新;金丝雀发布就是先发布一个v2版本,让其接受一小部分的流量,大部分流量仍然是在老版本上;如果v2版本运行ok,就把其他的v2版本依次发布;如果v2版本有问题,则退回老版本
    • 也称灰度发布,是指在黑白之间能够平滑过渡的一种发布方式;可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度
  2. 金丝雀发布步骤

    • 将www服务www-web-deployment扩容到3个实例
      • k8s/uat/www-web.yaml中replica改为3
      • kubectl get pods查看pod情况
      • kubectl apply -f www-web.yaml
      • kubectl get deployments查看实例个数
    • 发布金丝雀 www-web-deployment-canary
      • k8s/uat/canary/www-web-canary.yaml中image改为boboweike/www-svc:blue
      • kubectl apply -f canary
    • 校验
    • 扩容金丝雀到3个实例
      • k8s/uat/canary/www-web-canary.yaml中replicas改为3
      • kubectl apply -f canary
      • kubectl get deployments查看实例个数
    • 删除www-web-deployment
      • kubectl get deployments查看实例个数
      • k8s/uat/canary/www-web.yaml中replicas改为0
      • kubectl apply -f www-web.yaml
      • kubectl get deployments查看实例个数

阿里云资源释放

  1. 释放aliyun RDS

    • 云数据库RDS版本,更多,释放实例,短信验证码,确定
  2. 释放k8s

    • 容器服务Kubernetes版,更多,删除,已知晓,确定
    • 日志服务,project列表,删除
  3. 专有网络VPC

    • 不产生费用,可不删
    • 如果要删除,先删交换机,再删VPC

「真诚赞赏,手留余香」

WZhong

真诚赞赏,手留余香

使用微信扫描二维码完成支付