.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,能夠實現服務在集羣內部互相訪問。

相關文章
相關標籤/搜索