将分布式项目sck-demo部署到本地kubernetes,以及实现版本升级和回滚

447 阅读7分钟

博客搬家-原文链接

本篇将一步步介绍如何将sck-demo整个项目部署到本地kubernetes,包括镜像升级、让服务可通过浏览器访问、回滚版本,以及调整minikube虚拟机的内存大小。

项目地址:https://github.com/wujiuye/share-projects/tree/master/sck-demo

修改minikube的cpu核心数量和内存大小

先来说说如何调整minikube虚拟机的内存大小。默认的minikube虚拟机分配的内存很小,如果不调整大小,你会发现,pod一起动起来,要么一会挂掉,要么就是其它服务的pod挂掉。不过对sck-demo来说默认的内存大小是足够的。

  • 1、如果已经启动过minikube,则需要先删除
minikube delete
  • 2、启动时指定虚拟机的cpu和内存大小
 minikube start --image-mirror-country='cn' \
--image-repository='registry.cn-hangzhou.aliyuncs.com/google_containers' \
--cpus 2 --memory 4g \
--vm-driver=virtualbox

或者先修改配置,再执行minikube delete,再重新启动

minikube config set memory 4096

建议:如果本地机器内存少于8g,不建议在本地搞minikube,不然电脑会很卡。

为容器配置预估的应用需要消费的cpu资源和内存大小(resources项):

将jar包构建为镜像

将项目打包,然后构建镜像,构建镜像时应该打上tag,标志着每个镜像的版本号,启动一个服务也应该明确地指定镜像的版本,而不是使用默认latest

  • 1、项目打包
mvn clean package -DskipTests
  • 2、确保minikube已经启动,确保使用minikube docker守护进程

为使镜像自动存在,而不需要将镜像推送至远程仓库再拉取,可以使用与minikube vm相同的docker主机构建镜像。

eval $(minikube docker-env)

如果不再使用minikube主机时,可以通过运行eval $(minikube docker-env -u)来撤消此更改:

eval $(minikube docker-env -u)
  • 3、使用minikubedocker守护进程构建镜像

sck-demo项目的其中一个模块为例:

docker build -t wujiuye/sck-demo-provider:v1.0.0 ./sck-demo-provider

命令参数说明:

  • -t: 构建镜像并打标签;
  • wujiuye/sck-demo-provider:v1.0.0:镜像标签;
  • ./sck-demo-providerDockerfile文件所在目录

同样步骤,将sck-demo-consumer构建为镜像。

编写各描述文件,将镜像部署到minikube

  • 1、为服务提供者和服务消费者都编写DeploymentService描述文件,这两个配置写在同一个yaml文件。

sck-demo-provider为例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sck-demo-provider
  namespace: default
spec:
  # 副本数
  replicas: 1
  selector:
    matchLabels:
      app: sck-demo-provider
  template:
    metadata:
      labels:
        app: sck-demo-provider
        env: dev
    spec:
      # 容器配置
      containers:
        - name: sck-demo-provider
          image: wujiuye/sck-demo-provider:v1.0.0
          # 镜像拉去策略:Always(总是拉取)、IfNotPresent(默认值,本地有则使用本地镜像,不拉取)、Never(只使用本地镜像,从不拉取)
          imagePullPolicy: Never
          ports:
            - name: http-port
              containerPort: 8080
          # 环境变量,引用ConfigMap资源,sck-demo-common-config为通用环境变量配置
          envFrom:
            - configMapRef:
                name: sck-demo-common-config
      # 指定ServiceAccount,稍后创建
      serviceAccountName: pod-configmap-sa
# 使用---分割配置
---
apiVersion: v1
kind: Service
metadata:
  name: sck-demo-provider
  namespace: default
spec:
  selector:
    app: sck-demo-provider
    env: dev
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

其中sck-demo-common-config的配置如下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: sck-demo-common-config
  namespace: default
data:
  SPRING_PROFILES_ACTIVE: dev
  SERVER_PORT: "8080"

sck-demo-common-config为通用环境变量配置,也是ConfigMap资源。

使用kubectl创建名为sck-demo-common-configConfigMap资源:

kubectl apply -f k8s/dev/config/sck-demo-common-config.yaml

使用kubectl创建sck-demo-provider服务的DeploymentService

kubectl apply -f k8s/dev/service/sck-demo-provider.yaml

  • 2、由于sck-demo项目使用到动态配置,因此还需要为每个服务(使用到动态配置的服务)编写ConfigMap资源配置文件。

sck-demo-provider为例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: sck-demo-provider-config
  namespace: default
data:
  ## 动态配置内容
  application-dev.yml: |-
    sck-demo:
      message: for dev config map

使用kubectl创建ConfigMap

kubectl apply -f k8s/dev/config/sck-demo-provider-config.yaml

  • 3、添加一个用户,并为用户授权,应用程序读取ConfigMap资源配置时需要用到。

创建一个ServiceAccount

# 创建ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: pod-configmap-sa
  namespace: default

创建角色pod-configmap-read-role

# 创建角色(pod级别)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-configmap-read-role
  namespace: default
# 注册中心需要services的访问权限
rules:
  - apiGroups: [""]
    # 该角色可以访问的资源
    resources: ["pods","configmaps","endpoints","services"]
    # 限定能做哪些操作
    verbs: ["get", "watch", "list"]

ServiceAccount与角色绑定:

# 为指定ServiceAccount绑定角色
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-configmap-read-role-binding
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pod-configmap-read-role
subjects:
  - kind: ServiceAccount
    name: pod-configmap-sa
    namespace: default

将这三个文件放在同一个目录account,最后使用kubectl创建用户、角色、以及将用户与角色绑定:

kubectl apply -f k8s/dev/account

测试服务间调用,测试动态配置

如果我们只是想测试sck-demo-consumer调用sck-demo-provider能否成功,我们可以选择只暴露sck-demo-consumer。由于动态配置是写在sck-demo-provider的,并且提供了api来验证动态配置是否生效,因此也需要将sck-demo-provider暴露到外部可访问。

修改sck-demo-providersck-demo-consumerService配置,将集群IP类型改为NodePort

  • sck-demo-consumer.yaml
apiVersion: v1
kind: Service
metadata:
  name: sck-demo-consumer
  namespace: default
spec:
  selector:
    app: sck-demo-consumer
    env: dev
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: NodePort
  • sck-demo-provider.yaml
apiVersion: v1
kind: Service
metadata:
  name: sck-demo-provider
  namespace: default
spec:
  selector:
    app: sck-demo-provider
    env: dev
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: NodePort

更新Service

kubectl apply -f k8s/dev/service

其中k8s/dev/service目录存放sck-demo项目的dev环境下所有服务的DeploymentService配置的配置文件。

使用minikube service命令暴露服务,让本地可访问。

暴露sck-demo-consumer服务:

minikube service sck-demo-consumer

暴露sck-demo-provider服务:

minikube service sck-demo-provider

在浏览器访问http://192.168.99.103:30462/demo,验证服务是否调用成功,如果如下:

修改sck-demo-provider-config.yaml文件,或者直接在kubernetes dashboard修改,验证动态配置是否生效。

如图,我们将sck-demo.message修改为for dev config map yyyyy,修改完成后点击update,接着浏览器访问:http://192.168.99.103:31424/v1/config:

接收动态配置的bean:

@Component
@ConfigurationProperties(prefix = "sck-demo")
@RefreshScope(proxyMode = ScopedProxyMode.TARGET_CLASS)
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class DemoProps {
    private String message;
}

注意:在测试时,不要将DemoProps写到响应体,否则会报序列化异常,因为这是一个动态代理对象,我们在分析动态配置实现源码后再回过头来看就不难理解了。

在上一篇文章中,我们添加了监听动态配置刷新事件并打印日记的代码,因此,现在我们还可以使用kubectl logs查看Pod输出的日记:

kubectl logs pod的name

镜像版本升级

  • 1、构建镜像时带上新版本号,假设新的版本号为v1.0.1
docker build -t wujiuye/sck-demo-provider:v1.0.1 ./sck-demo-provider

Deployment做一次升级

kubectl set image deployment deployment名称 容器名称=镜像版本

kubectl set image deployment sck-demo-provider sck-demo-provider=wujiuye/sck-demo-provider:v1.0.1

命令执行成功后,会启动新的Pod,当新的Pod启动成功后,旧的Pod会被移除。新Pod的描述文件容器配置部分将会更新为如下:

spec:
    containers:
       - name: sck-demo-provider
        image: 'wujiuye/sck-demo-provider:v1.0.1'

版本回退

sck-demo-provider为例:

在更新Deployment时加上--record,记录本次执行的命令,以便后续查看历史记录时,能够看出每个版本都做了什么,能够判断需要回滚到哪个版本。

 kubectl set image Deployment sck-demo-provider sck-demo-provider=wujiuye/sck-demo-provider:v1.0.3 --record

查看历史版本:

kubectl  rollout history deployment sck-demo-provider --namespace=default

回滚到某个版本:

kubectl rollout undo deployment sck-demo-provider --to-revision=10 --namespace=default
  • --to-revision:指定回滚到哪个版本
  • --namespace:名称空间
  • sck-demo-provider:需要回滚的deployment的名称

如上图所示,回滚成功后,版本10就更新成新的版本号了。

通过-o wide查看deployment状态信息:

kubectl get deployment sck-demo-provider -o wide

查看replicaset每个版本的状态信息:

kubectl get replicaset

可使用revisionHistoryLimit控制ReplicaSet的历史版本保留数量,默认为10