Kubernetes微服务常见概念及应用

理解k8s架构

两类角色:master节点和worker节点。master用于调度和管理集群资源,worker节点是资源的提供者。worker节点提供的资源单位叫pod,可以理解为k8s云平台提供的虚拟机,pod中存放的是应用容器,比如docker容器。容器是cpu和内存的资源隔离单位,大部分情况下一个pod中只住一个应用容器,也有一个主容器多个辅助容器的情况,一个pod内的容器共享网络栈和存储资源。

k8s主要解决集群资源调度问题,当有应用发布请求,k8s根据集群资源空闲状况,将应用的pod分配到空闲的worker节点上,同时k8s时刻监控集群,有节点挂了需要重新协调及启动pod保证应用高可用。(自愈)

master节点组件构成

etcd:集中的状态存储,所有的集群状态数据包括节点、pods、发布配置等。是一个分布式的KV数据库,采用raft分布式一致性算法。

API server:其他组件操作etcd的代理,只有API server可以操作etc;事件总线,通知给订阅的外围组件。

Scheduler:调度决策的组件。

Controller manager:确保实际状态与预期状态最终一致的组件。

worker节点组件构成

Kubelet:worker组件的资源管理者,监听Api Server事件,根据master节点的指示做相关的动作,将本节点的状态数据汇报给master节点。

Container Runtime:Kubelet不直接管理节点上的容器资源,委托给Container Runtime管理,如启动关闭容器,收集容器状态等。在启动容器时,如果本地没有镜像缓存就会拉取Docker Hub上的相应镜像缓存到本地。

Kube-proxy:管理k8s服务网络的组件。pod的ip是不固定的,Service屏蔽了po d的ip,并在调用时进行负载均衡。当需要将k8s中的服务暴露给外网时,也需要Kube-proxy进行代理转发。

发布流程样例

假设使用kubectl创建ReplicaSet请求,API server将请求存储在etcd中,在监听中的Controller manager收到通知,比较当前状态与预期状态不一致则会创建pod,根据kubectl提供的pod模版创建预期的pod资源;监听中的Scheduler收到通知,会运行调度算法选择空闲的worker节点,通过Api server更新pod的定义,将pod指派到具体要发布到哪些worker节点上;Api server通知相应节点上的kubelet,指示Container Runtime去运行对应容器;Container Runtime去下载镜像启动容器,kubelet监控容器运行,到此则是一个完整的应用发布流程样例。

kubectl操作发布流程

创建yaml文件:

apiVersion: v1kind: Pod metadata:   name: petclinicspec:  containers: # 容器镜像名称    - name: petclinic      image: spring2go/spring-petclinic:1.0.0.RELEASE

根据yaml创建pod:kubectl apply -f petclinic-pod.yml

查看所有pod:kubectl get all

查看具体pod:kubectl get pod petclinic;kubectl describe pod petclinic

将服务端口指到pod端口(仅在本地或测试用):kubectl port-forward petclinic 8080:8080

删除pod:kubectl delete pod petclinic

添加反向代理service。petclinic-svc.yml:

apiVersion: v1kind: Servicemetadata:  name: petclinicspec:  ports:    - name: http      port: 8080 # servic本身暴露的端口,集群内部的端口      targetPort: 8080 # 对接的pod的端口      nodePort: 31080 # 在本机的31080端口暴露service  selector:    app: petclinic # 找到对应标签的pod  type: NodePort

petclinic-pod.yaml:

apiVersion: v1kind: Pod metadata:   name: petclinic  labels: # 为路由选择打标签    app: petclinicspec:  containers: # 容器镜像名称    - name: petclinic      image: spring2go/spring-petclinic:1.0.0.RELEASE

蓝绿发布

新版本和旧版本的pod,修改对应版本号即可。

apiVersion: v1kind: Pod metadata:   name: petclinic-v1.0.0  labels: # 为路由选择打标签    app: petclinic    version: v1.0.0spec:  containers: # 容器镜像名称    - name: petclinic      image: spring2go/spring-petclinic:1.0.0.RELEASE​​​​​
apiVersion: v1kind: Podmetadata:  name: petclinic-v1.0.1  labels:    app: petclinic    version: v1.0.1spec:   containers:    - name: petclinic      image: spring2go/spring-petclinic:1.0.1.RELEASE

发布service,修改对应版本号实现新老版本切换

apiVersion: v1kind: Servicemetadata:  name: petclinicspec:   ports:    - name: http      port: 8080      targetPort: 8080      nodePort: 31080  selector:    app: petclinic    version: v1.0.1  type: NodePort

应用集群抽象

应用集群抽象Replicates副本集,应用到了k8s的自愈能力。

petclinic-replicates.yml:

apiVersion: apps/v1kind: ReplicaSetmetadata:  name: petclinicspec:   replicas: 3  # 发布3个实例  selector:    matchLabels:      app: petclinic  # 给pod打的标签  template:    metadata:      labels:        app: petclinic    spec:       containers:        - name: petclinic          image: spring2go/spring-petclinic:1.0.0.RELEASE

replicas中发布了3个实例,当其中有实例挂掉,k8s会重启一个实例以维持集群中始终有3个实例。

滚动发布抽象Deployment

滚动发布Rolling Update是一种发布策略,按批次依次替换老版本,逐步升级到新版本,发布过程中应用不中断。k8s中的Deployment是对Replicaset+滚动发布流程的一种包装。滚动发布适用于版本兼容,蓝绿发布适用于版本不兼容发布。

假设绿色版本已经发布,对应的Replicaset为v1.0.0,通过Deployment升级发布到v1.0.1,发布之后会创建新的Replicaset v1.0.1,之后Deployment会依次滚动,不断创建并拉入蓝色版本的pod,拉出并关闭绿色版本的pod,直到所有蓝色的pod都上线绿色版本的pod都下线。此过程中Deployment始终保持有可用pod,服务不会中断,而且前置的service会屏蔽掉内部ip的变化,实现无感发布。新版本有问题也可回退,方法同理。

petclinic-deployment.yml:​​​​​​​

apiVersion: apps/v1kind: Deploymentmetadata:  name: petclinicspec:   selector:    matchLabels:      app: petclinic  minReadySeconds: 10  # 测试用,启动后10s状态才变为就绪  replicas: 3  template:    metadata:      labels:        app: petclinic # 与matchLabels下对应的app相同    spec:      containers:        - name: petclinic          image: spring2go/spring-petclinic:1.0.1.RELEASE

查看发布历史:kubectl rollout history deployment/petclinic

回退发布:kubectl rollout undo deployment/petclinic

指定回退版本:kubectl rollout undo deployment/petclinic --to-revision=2

动态查看发布进度:kubectl rollout status deployment/petclinic

理解k8s的ClusterIP Service

k8s内部服务之间访问引入反向代理抽象,实现反向路由和负载均衡,内部使用ClusterIP 类型的service,k8s内部为避免pod的ip变化,使用解析app服务名的方式,找到对应服务集群。

假设将mysql通过k8s发布(一般来说mysql是一个单独服务,这里仅用于示例展示),有状态的服务一般只能部署一个pod实例。

mysql-pod.yml​​​​​​​

apiVersion: v1kind: Podmetadata:  name: mysql  labels:     app: mysqlspec:  containers:    - name: mysql      image: mysql:5.7      env:        - name: MYSQL_ROOT_PASSWORD          value: petclinic        - name: MYSQL_DATABASE          value: petclinic

mysql-service.yml​​​​​​​

apiVersion: v1kind: Servicemetadata:  name: mysqlspec:  selector:    app: mysql  ports:    - name: tcp      port: 3306      targetPort: 3306  type: ClusterIP

petclinic-deployment.yml

apiVersion: apps/v1kind: Deploymentmetadata:  name: petclinicspec:   selector:    matchLabels:      app: petclinic  replicas: 1  template:    metadata:      labels:        app: petclinic    spec:      containers:        - name: petclinic          image: spring2go/spring-petclinic:1.0.1.RELEASE          env:             - name: SPRING_PROFILES_ACTIVE              value: mysql            - name: DATASOURCE_URL              value: jdbc:mysql://mysql/petclinic            - name: DATASOURCE_USERNAME              value: root            - name: DATASOURCE_PASSWORD              value: petclinic            - name: DATASOURCE_INIT_MODE              value: always

petclinic-service.yml

apiVersion: v1kind: Servicemetadata:  name: petclinicspec:   ports:    - name: http      port: 8080      targetPort: 8080      nodePort: 31080  selector:    app: petclinic  type: NodePort

查看pod启动日志:kubectl logs petclinic-cb946d644-5r7q9

k8s Service的三种类型:

  • ClusterIP:内部服务访问

  • NodePort:对外暴露服务

  • LoadBalancer:对外暴露服务(公有云)

k8s名字空间抽象Namespace

Namespace是k8s中的逻辑隔离机制,一个k8s集群中可以配置多个Namespace,每个Namespace中住着独立的pod、service、replicasets等资源,不同Namespace之间的资源可以相互访问,可以使用kubectl get ns来看k8s内置的已经支持的名字空间,其中default是缺省名字空间,kube-system是系统名字空间其中是支持k8s运行的系统组件。也可以根据不同业务定制不同名字空间,比如按业务线划分,或者按功能分类如前、后端、监控等划分。

查看对应名字空间下的组件:kubectl get all -n kube-system

如kube-dns就是k8s内置的dns域名解析服务,coredns是它下的两个pod。

以终端交互的方式运行pod下的shell命令:kubectl exec -it petclinic-cb946d644-5r7q9 sh

我们进入pod查看发现,拼装成全域名以后查到对应的ip地址。所以单用mysql查不到,他的域名是10.101.75.79 mysql.default.svc.cluster.local。

K8s配置抽象ConfigMap

需要根据环境的不同使用不同配置,这些配置有些是在启动时一次性配置好,如:数据库连接字符串,还有些配置可以在运行期动态调整的,如:缓存的过期时间TTL值,业务相关配置数据等。k8s平台内置支持微服务配置即ConfigMap。

开发人员将配置填写在ConfigMap中,发布后k8s将ConfigMap以环境变量的形式注入到pod中,这样pod中的应用可以用环境变量的形式访问这些配置,ConfigMap也支持以存储卷Volume方式挂载到pod中,实现配置热更新。

由于多个业务服务都需要连接数据库的配置,如果为每个服务增加配置会出现冗余和可维护问题,ConfigMap正好解决了这个问题。我们可以将配置统一放到公共的ConfigMap中,发布后k8s将ConfigMap中的配置注入到后台服务的pod中。

petclinic-config.yml

apiVersion: v1kind: ConfigMapmetadata:   name: petclinic-config-v2data:  SPRING_PROFILES_ACTIVE: mysql  DATASOURCE_URL: jdbc:mysql://mysql/petclinic  DATASOURCE_USERNAME: root  DATASOURCE_PASSWORD: petclinic  DATASOURCE_INIT_MODE: always  TEST_CONFIG: test_config_v2

mysql-svc.yml

apiVersion: v1kind: Podmetadata:  name: mysql  labels:     app: mysqlspec:  containers:    - name: mysql      image: mysql:5.7      env:        - name: MYSQL_ROOT_PASSWORD          value: petclinic        - name: MYSQL_DATABASE          value: petclinic---apiVersion: v1kind: Servicemetadata:  name: mysqlspec:  selector:    app: mysql  ports:    - name: tcp      port: 3306      targetPort: 3306  type: ClusterIP

petclinic-svc.yml

apiVersion: apps/v1kind: Deploymentmetadata:  name: petclinicspec:   selector:    matchLabels:      app: petclinic  replicas: 1  template:    metadata:      labels:        app: petclinic    spec:      containers:        - name: petclinic          image: spring2go/spring-petclinic:1.0.1.RELEASE          envFrom:             - configMapRef:                name: petclinic-config-v2---apiVersion: v1kind: Servicemetadata:  name: petclinicspec:   ports:    - name: http      port: 8080      targetPort: 8080      nodePort: 31080  selector:    app: petclinic  type: NodePort

发布配置文件:kubectl apply -f petclinic-config.yml

查看configMap:kubectl get cm

查看petclinic-config详情:kubectl describe cm petclinic-config

发布mysql-svc.yml及petclinic-svc.yml:kubectl apply -f mysql-svc.yml;kubectl apply -f petclinic-svc.yml

打印出pod下全部环境变量:kubectl exec petclinic-f77f5c8f-bjvxl printenv

指定打印pod下某个环境变量:kubectl exec petclinic-f77f5c8f-bjvxl printenv | grep TEST_CONFIG

配置更新需要重启pod,建议更新ConfigMap的name及其引用。

微服务网关

微服务网关:微服务网关的主要作用是将前端和后端微服务进行解耦,使得两边不直接依赖,可以独立变化。网关本质上是一个七层反向代理,当前端向某个微服务发起调用,由网关根据配置的路由表做路由转发,由于网关是后端微服务的集中入口,它还可以实现安全认证、限流熔断、日志监控、解耦迁移和金丝雀测试等功能。

K8s ingress

在公有云的k8s环境中要将微服务暴露到公网,我们需要申请负载均衡器(Load Balancer),由于LB需要购买,而且暴露一个服务就需要购买一个LB,当微服务数量多时,显然从成本角度考虑,这种做法是不可扩展的。为解决这个问题k8s中引入了ingress组件,和网关类似,ingress本质上也是一个七层反向代理。引入ingress我们可以只购买一个或者少量LB,就可以将多个微服务暴露出去,由ingress统一实现路由转发。每次要将服务暴露出去时,只需在ingress增加路由规则即可。ingress也是一个service服务,只不过它的功能时做路由转发,它也需要前置的LB才能将自己暴露出去。

ingress在k8s中主要是定义了规范,具体有很多种实现:

https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress-controllers/

代码来源:https://github.com/spring2go/k8s-msa-in-action 图片来源:https://github.com/spring2go/k8s-msa-in-action-ppt

我的个人公众号,“才浅coding攻略”,这里可以第一时间收到推送,期待你的关注和催更!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值