.Net Core 商城微服务项目系列(十二):使用k8s部署商城服务

1、简介docker

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

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

2.再也不使用Ocelot做为业务网关,使用Traefik来实现。浏览器

正如上面所讲,服务发现和网关均使用k8s的相关工具,固然,相比与以上两个工具,Traefik还有本身的不足,好比Consul的健康检查、Ocelot的限流、熔断机制,不过这些咱们后面能够经过其它方式来实现。app

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

 

2、打包镜像ide

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"]

经过如下命令进行打包:post

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"]

 

3、部署到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来实现。

 

3、使用k8s-dns作服务发现

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

kube-dns能够解决Service的发现问题,k8s将Service的名称当作域名注册到kube-dns中,经过Service的名称就能够访问其提供的服务。

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

相关文章
相关标签/搜索