前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kubernetes微服务常见概念及应用

Kubernetes微服务常见概念及应用

作者头像
才浅Coding攻略
发布2022-12-12 18:15:20
7730
发布2022-12-12 18:15:20
举报
文章被收录于专栏:才浅coding攻略才浅coding攻略

理解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可以操作etcd;事件总线,通知给订阅的外围组件。

Scheduler:调度决策的组件。

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

worker节点组件构成

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

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

Kube-proxy:管理k8s服务网络的组件。pod的ip是不固定的,Service屏蔽了pod的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文件:

代码语言:javascript
复制
apiVersion: v1
kind: Pod 
metadata: 
  name: petclinic
spec:
  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:

代码语言:javascript
复制
apiVersion: v1
kind: Service
metadata:
  name: petclinic
spec:
  ports:
    - name: http
      port: 8080 # servic本身暴露的端口,集群内部的端口
      targetPort: 8080 # 对接的pod的端口
      nodePort: 31080 # 在本机的31080端口暴露service
  selector:
    app: petclinic # 找到对应标签的pod
  type: NodePort

petclinic-pod.yaml:

代码语言:javascript
复制
apiVersion: v1
kind: Pod 
metadata: 
  name: petclinic
  labels: # 为路由选择打标签
    app: petclinic
spec:
  containers: # 容器镜像名称
    - name: petclinic
      image: spring2go/spring-petclinic:1.0.0.RELEASE

蓝绿发布

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

代码语言:javascript
复制
apiVersion: v1
kind: Pod 
metadata: 
  name: petclinic-v1.0.0
  labels: # 为路由选择打标签
    app: petclinic
    version: v1.0.0
spec:
  containers: # 容器镜像名称
    - name: petclinic
      image: spring2go/spring-petclinic:1.0.0.RELEASE
代码语言:javascript
复制
apiVersion: v1
kind: Pod
metadata:
  name: petclinic-v1.0.1
  labels:
    app: petclinic
    version: v1.0.1
spec: 
  containers:
    - name: petclinic
      image: spring2go/spring-petclinic:1.0.1.RELEASE

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

代码语言:javascript
复制
apiVersion: v1
kind: Service
metadata:
  name: petclinic
spec: 
  ports:
    - name: http
      port: 8080
      targetPort: 8080
      nodePort: 31080
  selector:
    app: petclinic
    version: v1.0.1
  type: NodePort

应用集群抽象

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

petclinic-replicates.yml:

代码语言:javascript
复制
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: petclinic
spec: 
  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:

代码语言:javascript
复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: petclinic
spec: 
  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

代码语言:javascript
复制
apiVersion: v1
kind: Pod
metadata:
  name: mysql
  labels: 
    app: mysql
spec:
  containers:
    - name: mysql
      image: mysql:5.7
      env:
        - name: MYSQL_ROOT_PASSWORD
          value: petclinic
        - name: MYSQL_DATABASE
          value: petclinic

mysql-service.yml

代码语言:javascript
复制
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  selector:
    app: mysql
  ports:
    - name: tcp
      port: 3306
      targetPort: 3306
  type: ClusterIP

petclinic-deployment.yml

代码语言:javascript
复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: petclinic
spec: 
  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

代码语言:javascript
复制
apiVersion: v1
kind: Service
metadata:
  name: petclinic
spec: 
  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

代码语言:javascript
复制
apiVersion: v1
kind: ConfigMap
metadata: 
  name: petclinic-config-v2
data:
  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

代码语言:javascript
复制
apiVersion: v1
kind: Pod
metadata:
  name: mysql
  labels: 
    app: mysql
spec:
  containers:
    - name: mysql
      image: mysql:5.7
      env:
        - name: MYSQL_ROOT_PASSWORD
          value: petclinic
        - name: MYSQL_DATABASE
          value: petclinic
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  selector:
    app: mysql
  ports:
    - name: tcp
      port: 3306
      targetPort: 3306
  type: ClusterIP

petclinic-svc.yml

代码语言:javascript
复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: petclinic
spec: 
  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: v1
kind: Service
metadata:
  name: petclinic
spec: 
  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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 才浅coding攻略 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 理解k8s架构
  • master节点组件构成
  • worker节点组件构成
  • 发布流程样例
  • kubectl操作发布流程
  • 滚动发布抽象Deployment
  • 理解k8s的ClusterIP Service
  • k8s名字空间抽象Namespace
  • K8s配置抽象ConfigMap
  • 微服务网关
  • K8s ingress
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档