zoukankan      html  css  js  c++  java
  • .Net Core 商城微服务项目系列(十二):使用k8s部署商城服务

    一、简介

    本篇我们将会把商城的服务部署到k8s中,同时变化的还有以下两个地方:

    1.不再使用Consul做服务的注册和发现,转而使用k8s-dns来实现。

    2.不再使用Ocelot作为业务网关,使用Traefik来实现。

    正如上面所讲,服务发现和网关均使用k8s的相关工具,当然,相比与以上两个工具,Traefik还有自己的不足,比如Consul的健康检查、Ocelot的限流、熔断机制,不过这些我们后面可以通过其它方式来实现。

    整体思路很简单哈,就是编写Dockerfile文件,将各个服务打包成镜像上传到DockerHub,然后再我们的k8s集群中部署,并使用Traefik路由。

    二、打包镜像

    Dockerfile文件都一样的,所以我这里只列出IdentityServer4服务的Dockerfile:

    FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
    WORKDIR /app
    EXPOSE 80
    
    FROM microsoft/dotnet:2.1-sdk AS build
    WORKDIR /src
    Copy . .
    
    RUN dotnet restore
    RUN dotnet build -c Release -o /app
    
    FROM build as publish
    RUN dotnet publish -c Releease -o /app
    
    FROM base AS final
    WORKDIR /app
    COPY --from=publish /app .
    ENTRYPOINT ["dotnet", "MI.Service.Identity.dll"]

    通过以下命令进行打包:

    docker build -t 镜像名 .

    这里需要注意的是镜像名要用自己DockerHub的用户名作为前缀,比如 用户名/mi.service.identity ,只有这样才能再后面上传镜像。

    然后通过以下命令登录Docker,上传镜像:

    docker login --username xxx
    
    
    docker push 用户名/mi.service.identity

    这里需要注意的是如果我们的项目是包含类库的,比如下面这种:

    那我们的Dockerfile文件写法要改成下面这样,并且要把它放在和解决方案.sln同级的文件夹内,因为类库也需要进行编译:

    FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
    WORKDIR /app
    EXPOSE 80

    FROM microsoft/dotnet:2.1-sdk AS build
    WORKDIR /src
    Copy . .

    WORKDIR /src/MI.Service.Account

    RUN dotnet restore
    RUN dotnet build -c Release -o /app

    FROM build as publish
    RUN dotnet publish -c Releease -o /app

    FROM base AS final
    WORKDIR /app
    COPY --from=publish /app .
    ENTRYPOINT ["dotnet", "MI.Service.Account.dll"]

    三、部署到k8s

    我们的需要编写deployment、Service和ingress的yaml文件,分别如下

    kind: Deployment
    apiVersion: apps/v1
    metadata:
      labels:
        k8s-app: mi-service
      name: mi-service-identity
      namespace: mi
    spec:
      replicas: 2
      selector:
        matchLabels:
          k8s-app: mi-service-identity
      template:
        metadata:
          labels:
            k8s-app: mi-service-identity
        spec:
          containers:
          - name: mi-service-identity
            image: 用户名/mi.service.identity
            ports:
            - containerPort: 80
    apiVersion: v1
    kind: Service
    metadata:
      name: mi-service-identity
      namespace: mi
    spec:
      selector:
        k8s-app: mi-service-identity
      ports:
      - name: http
        port: 80
        targetPort: 80
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: mi-service
      namespace: mi
    spec:
      rules:
      - host: mi.service.identity
        http:
          paths:
          - path: /
            backend:
              serviceName: mi-service-identity
              servicePort: http

    通过以下命令部署(拉取镜像需要点时间):

    kubectl apply -f mi_identity.yaml
    kubectl apply -f mi_identity_service.yaml
    kubectl apply -f mi-service-ingress.yaml

    完成后查看svc、pod、ingress的状态:

    [root@localhost ~]# kubectl get pods -n mi
    NAME                                 READY   STATUS    RESTARTS   AGE
    mi-service-identity-7dfbf85d-x7w82   1/1     Running   0          23h
    mi-service-identity-7dfbf85d-z4hz9   1/1     Running   0          23h
    
    
    [root@localhost ~]# kubectl get deployment -n mi
    NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
    mi-service-identity   2/2     2            2           23h
    
    
    [root@localhost service-yaml]# kubectl get svc -n mi
    NAME                  TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
    mi-service-identity   ClusterIP   10.109.13.2   <none>        80/TCP    7s
    
    [root@localhost k8s-mi]# kubectl get ing -n mi
    NAME         HOSTS                 ADDRESS   PORTS   AGE
    mi-service   mi.service.identity             80      33m

    这个时候我们已经可以再集群内部访问了:

    [root@localhost service-yaml]# curl http://10.109.13.2/api/Health
    ok

    然后配置下Host文件,通过浏览器访问

    这个服务是用来获取token令牌的,所以呢我们需要postman测试下能不能获取到Token:

    成功!

    然后我们需要把另外的服务也部署到k8s,同时更新Ingress的配置,如下:

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: mi-service
      namespace: mi
    spec:
      rules:
      - host: mi.service.identity
        http:
          paths:
          - path: /
            backend:
              serviceName: mi-service-identity
              servicePort: http
      - host: mi.service.account
        http:
          paths:
          - path: /
            backend:
              serviceName: mi-service-account
              servicePort: http
      - host: mi.service.monitor
        http:
          paths:
          - path: /
            backend:
              serviceName: mi-service-monitor
              servicePort: http
     - host: mi.service.picture
        http:
          paths:
          - path: /
            backend:
              serviceName: mi-service-picture
              servicePort: http
      - host: mi.service.shopcar
        http:
          paths:
          - path: /
            backend:
              serviceName: mi-service-shopcar
              servicePort: http

    这个时候其实我们已经可以正常使用了,我们将Web项目里的服务地址修改下,不再通过调用Ocelot进行转发,而是使用k8s中Service的标识,修改appsettings:

    {
      "Logging": {
        "IncludeScopes": false,
        "LogLevel": {
          "Default": "Warning"
        }
      },"ServiceAddress": {
        "Service.Identity": "http://mi.service.identity",
        "Service.Account": "http://mi.service.account","Service.Picture": "http://mi.service.picture",
        "Service.Monitor": "http://mi.service.monitor",
        "Service.ShopCar": "http://mi.service.shopcar"
      }
    }

    然后运行项目查看:

     

     但是我们现在还存在一个问题。虽然Pod的IP可以被Service发现,但是Service的IP被谁发现呢,现在Traefik中配置host和其IP是我们手动配置,当然Service的IP一般是固定不变的,但是如果变了,我们希望能被自动发现和映射,这一步将通过k8s dns来实现。

    三、使用k8s-dns做服务发现

    k8s中的service分配的虚拟IP是固定的,而pod异常后新生成的pod ip会发生变化,可以通过service做代理关联到后端的pod。

    kube-dns可以解决Service的发现问题,k8s将Service的名称当做域名注册到kube-dns中,通过Service的名称就可以访问其提供的服务。

    通过设置k8s中的dns服务可以直接解析service的名字,得到对应service的ip,可以实现服务在集群内部互相访问。

  • 相关阅读:
    linux下进程的实际用户ID(有效组)和有效用户ID(有效组ID)
    ubuntu下软件中心闪退问题解决
    LINUX(UNIX)文件I/O学习
    ubunut下桌面文件路径修改
    ubuntu下设置jdk/jre环境
    Fire net
    JavaScript 自己写一个 replaceAll() 函数
    Canvas 绘制一个像素风电子时钟
    Python3 笔记01:求两数之和
    尝试笔记 01 之 CSS 边角上的标签
  • 原文地址:https://www.cnblogs.com/weiBlog/p/10604961.html
Copyright © 2011-2022 走看看