将分布式项目sck-demo部署到本地kubernetes

原创 吴就业 108 0 2020-06-23

本文为博主原创文章,未经博主允许不得转载。

本文链接:https://wujiuye.com/article/e00f3e21700d49edbc21369561773090

作者:吴就业
链接:https://wujiuye.com/article/e00f3e21700d49edbc21369561773090
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。

本篇文章写于2020年06月23日,从公众号|掘金|CSDN手工同步过来(博客搬家),本篇为原创文章。

本篇文章由原来的两篇文章合并为一篇:

  • 《搭建本地Kubernetes集群与部署微服务》
  • 《将分布式项目sck-demo部署到本地kubernetes,以及实现版本升级和回滚》

Spring Cloud Kubernetes微服务实战与源码分析

使用minikube在本地安装单节点Kubernetes集群

在安装minikube之前需要先安装一个虚拟机,如VirtualBoxVMWare Fusion

为什么要装虚拟机呢?因为安装minikube只是用来搭建Kubernetes集群的工具,而minikube是在虚拟机上搭建的Kubernetes集群。首次启动minikube的过程很慢,因为minikube需要下载安装Kubernetes所需要的镜像。

如果使用VMWare Fusion,在启动minikube时可能会遇到一些坑,作为初学者,我们肯定不想一开始就折腾,卡住学习的进度,因此笔者建议大家安装VirtualBox

第一步:安装kubectl

brew install kubernetes-cli

第二步:安装虚拟机

VirtualBox的安装跳过。

第三步:安装minikube:

brew install minikube

启动minikube,由minikube在虚拟机上安装Kubernetes集群。

首次启动minikube需要指定虚拟机驱动--vm-driver,并指定拉取安装Kubernetes时需要拉取的一些镜像文件的仓库地址为阿里云提供的镜像仓库地址,如果你有vpn,那么可以不考虑。

minikube start --vm-driver=virtualbox \
--image-mirror-country='cn' \
--image-repository='registry.cn-hangzhou.aliyuncs.com/google_containers'

每种虚拟机对应的--vm-driver的值可到官网了解,这里列出两种常用的:

img

后续启动不需要再指定一大堆参数:

minikube start

电脑重启之后启动:

minikube start --image-mirror-country='cn' \
--image-repository='registry.cn-hangzhou.aliyuncs.com/google_containers'

查看状态:

minikube status

img

启动dashboard

minikube dashboard

img

停止minikube:

minikube stop

如何在本地单节点Kubernetes集群上部署服务

首先确保本地机器上已经安装了VirtualBoxminikubeDockerkubectl

mac上安装docker可下载dmg安装,非常简单,还提供一个Docker dashboard可视化界面。下载链接:https://download.docker.com/mac/stable/Docker.dmg

第一步:项目打包

执行 mvn clean package -DskipTests 构建打包服务。

第二步:构建应用程序镜像

执行 docker-compose build 在本地(或jenkins)构建镜像。

第三步:将镜像push到镜像仓库

执行 docker image tag 打标签,再将镜像pushdocker hubpush之前需要先登陆。push到私有仓库也是一样的步骤。

第四步:配置kubectl

使用kubectl之前确保 ~/.kube/config 的配置已修改为Kubernetes服务提供的凭据。但使用minikube不需要配置,因为minikube在启动Kubernetes集群时就已经配置好了,但如果是使用阿里云的容器服务就需要修改配置。

第五步:配置secret(看情况,不是必须的步骤)

如果是使用私有的镜像仓库,则需要为kubernetes容器从私有镜像仓库拉取镜像提供secret

kubectl create --namespace=default secret \
docker-registry my-docker-reg-secret \
--docker-server=registry.cn-shenzhen.aliyuncs.com \
[email protected] \
--docker-password=xxxxx \
[email protected]

其中--namespace用于指定名称空间,因为不同名称空间下,secret是不共享的。

第六步:将服务部署到Kubernetes

执行 kubectl apply -f [配置文件] 部署服务。

例如:

kubectl apply -f demo-srv.yaml

将分布式项目sck-demo部署到本地kubernetes

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

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

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

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

minikube delete
 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

mvn clean package -DskipTests

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

eval $(minikube docker-env)

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

eval $(minikube docker-env -u)

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

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

命令参数说明:

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

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

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

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

创建一个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

更新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

镜像版本升级

如:

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

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

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

kubectl get deployment sck-demo-provider -o wide

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

kubectl get replicaset

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

#后端

声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。

文章推荐

OpenFeign与Ribbon源码分析总结与面试题

本篇介绍OpenFeign与Feign的关系、Feign底层实现原理、Ribbon是什么、Ribbon底层实现原理、Ribbon是如何实现失败重试的?

Spring Cloud Ribbon源码分析

本篇继续分析OpenFeign是如何与Ribbon整合、Ribbon是如何实现负载均衡的、Ribbon是如何从注册中心获取服务的。

Spring Cloud OpenFeign源码分析,为什么不导入Ribbon应用会启动不起来?

如果指定了URL,那么getOptional方法不会返回null,且返回的Client是LoadBalancerFeignClient,但不会抛出异常。如果不指定URL,则走负载均衡逻辑,走的是loadBalance方法,且抛出异常。

Spring Cloud kubernetes入门项目sck-demo

本篇我们将从一个简单的demo上手Spring Cloud kubernetes,当然,我们只用到Spring Cloud kubernetes的服务注册与发现、配置中心模块。

为什么要选择Spring Cloud Kubernetes?

选择Spring Cloud Kubernetes意味着我们想要将服务部署到Kubernetes集群,Spring Cloud Kubernetes为我们实现了Spring Cloud的一些接口,让我们可以快速搭建Spring Cloud微服务项目框架,并能使用Kubernetes云原生服务。

Spring Cloud Kubernetes入门必知运维知识之Kubernetes

作为开发者,只有足够了解容器技术,才能做好技术选型,以及开发部署在Kubernetes容器服务之上的应用应该要注意哪些问题。如果运维不了解代码,开发也不了解Kubernetes,谁能解决将服务迁移到Kubernetes上遇到的各种问题呢?