3.4 Kubernetes下的构建执行

未匹配的标注

整理环境

上一章中,我们通过Docker Compose已经创建了etcdaccountapigwTraefik多个镜像对应的容器。为了不被干扰,并且我们改用Kubetnetes作为容器编排,我们需要删除之前创建的容器。

docker rm -f apigw apigw2 account1 account2 account3 go_micro_traefik_proxy_1 etcd1

我们将Kubernetes搭建在了同网段的Windows下的Vmware虚拟机中,使用的是桥接模式。也就是我的Mac可以直接与虚拟机通讯。还不会搭建Kubernetes的小伙伴可以先看 Kubernetes 18.04集群安装教程(基于Centos7) 这篇文章进行搭建

网络配置与 1.2 环境的准备与安装 里的相同。

Kubernetes下搭建

由于配置有限,所以我只搭建了一个Master节点,没有搭建Node节点,并且通过污点,设置master允许pod创建

kubectl taint node k8s-master node-role.kubernetes.io/master-

以下操作都是在KubetnetesMaster节点做的

私有仓库

如果你使用的是公开公共仓库镜像,即不需要登陆,就可以下载的镜像,则可以跳过私有仓库这个步骤。

我的镜像已经开放了公有权限,可以直接下载,不需要进行验证。如果你想使用自己的镜像,请按照下面进行操作。

阿里云登陆

docker login --username=<your-name> registry.cn-shenzhen.aliyuncs.com
# <your-name> 是你在阿里云上的登陆名

在集群中创建保存授权令牌的 Secret

# 创建 Secret,命名为 regcred:

kubectl create secret docker-registry regcred --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email> -n <your-namespace>

# <your-registry-server> 是你的私有 Docker 仓库全限定域名(FQDN)
# <your-name> 是你的 Docker 用户名。
# <your-pword> 是你的 Docker 密码。
# <your-email> 是你的 Docker 邮箱。
# <your-namespace> 创建后的该密钥属于k8s集群中哪一个namespace的

举个栗子

kubectl create secret docker-registry regcred --docker-server=registry.cn-shenzhen.aliyuncs.com --docker-username=guaosi@vip.qq.com --docker-password=a123654 --docker-email=guaosi@vip.qq.com -n go-micro

# 注意: -n 后面是我想这个密钥归属于哪个namespace,即哪个namespace可以使用

在pod清单中加入使用密钥

apiVersion: v1
kind: Pod
metadata:
  name: private-reg
  namespace: <your-namespace>
spec:
  containers:
  - name: private-reg-container
    image: <your-private-image>
  imagePullSecrets: # 使用指定的密钥
  - name: regcred # 与上面创建的secret名称相同

初始化

命名空间

创建名字为go-micronamespace,我们把需要的poddeploysvcsecret等等都放在这个namespace下方便管理。

deploy/k8s/k8s-namespace.yml

apiVersion: v1
kind: Namespace
metadata:
  name: go-micro
  namespace: go-micro

执行

kubectl create -f deploy/k8s/k8s-namespace.yml

给Pod创建RBAC权限

deploy/k8s/k8s-pod-rbac.yml

apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: go-micro
  name: micro-services
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: micro-registry
  namespace: go-micro
rules:
  - apiGroups:
      - ""
    resources:
      - pods
    verbs:
      - get
      - list
      - patch
      - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: micro-registry
  namespace: go-micro
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: micro-registry # 要被绑定的ClusterRole的name
subjects:
  - kind: ServiceAccount
    name: micro-services # 要被绑定的serviceAccount的name
    namespace: go-micro

执行

kubectl create -f deploy/k8s/k8s-pod-rbac.yml

account

pod

account/deploy/k8s/k8s-pod-account.yml

apiVersion: apps/v1
kind: Deployment # pod部署
metadata:
  namespace: go-micro  # 都设置在一个命名空间下,相同网络
  name: svc-account
spec:
  replicas: 1 # pod 数量
  selector:
    matchLabels:
      app: svc-account
  template:
    metadata:
      labels:
        app: svc-account
    spec:
      containers:
        - name: svc-account
          command: [
            "/account",
            "--registry=kubernetes",
          ]
          image: registry.cn-shenzhen.aliyuncs.com/go_micro/account:v1.0
          imagePullPolicy: Always
      serviceAccountName: micro-services # serviceAccount的名称 用于权限
      #imagePullSecrets: # 使用指定的密钥,才能下载私有镜像
      #  - name: regcred

执行

kubectl create -f account/deploy/k8s/k8s-pod-account.yml

关于account的负载均衡,只需要扩容deployreplicas即可 kubectl scale –replicas=3 deployment/svc-account -n go-micro

svc

account/deploy/k8s/k8s-svc-account.yml

apiVersion: v1
kind: Service # 网络服务
metadata:
  name: svc-account
  namespace: go-micro # 都设置在一个命名空间下,相同网络
  labels:
    app: svc-account
spec:
  ports:
    - port: 8080 # 必须填写,否则报错
      protocol: TCP
  selector:
    app: svc-account

执行

kubectl create -f account/deploy/k8s/k8s-svc-account.yml

apigateway

pod

apigateway/deploy/k8s/k8s-pod-apigw.yml

apiVersion: apps/v1
kind: Deployment # pod部署
metadata:
  namespace: go-micro  # 都设置在一个命名空间下,相同网络
  name: svc-apigw
spec:
  replicas: 1  # pod 数量
  selector:
    matchLabels:
      app: svc-apigw
  template:
    metadata:
      labels:
        app: svc-apigw
    spec:
      containers:
        - name: svc-apigw
          command: [
            "/apigw",
            "--p=8091", # 只能用 = 不能用空格隔开
            "--registry=kubernetes",
          ]
          image: registry.cn-shenzhen.aliyuncs.com/go_micro/apigw:v1.0
          imagePullPolicy: Always
          ports:
            - containerPort: 8091
              name: apigw-port
      serviceAccountName: micro-services # serviceAccount的名称 用于权限
      #imagePullSecrets: # 使用指定的密钥,才能下载私有镜像
      #  - name: regcred

执行

kubectl create -f apigateway/deploy/k8s/k8s-pod-apigw.yml

关于apigateway的负载均衡,只需要扩容deployreplicas即可 kubectl scale –replicas=3 deployment/svc-apigw -n go-micro

svc

apigateway/deploy/k8s/k8s-svc-apigw.yml

apiVersion: v1
kind: Service # 网络服务
metadata:
  name: svc-apigw
  namespace: go-micro # 都设置在一个命名空间下,相同网络
  labels:
    app: svc-apigw
spec:
  type: NodePort
  ports:
    - port: 8091 # cluster模式访问的端口
      nodePort: 30088   #设置 nodeport 端口 30000-32767 此时
                      # targetPort:访问容器内部的端口,与containerPort值相同。 当没有设置targetPort时,此时targetPort的值与port相同
  selector:
    app: svc-apigw

执行

kubectl create -f apigateway/deploy/k8s/k8s-svc-apigw.yml

验证

> curl -X POST -d "username=guaosi&password=guaosi" http://192.168.1.200
:30088/account/register

`{"code":0,"message":""}`

下面继续使用Traefik来进行反向代理了。

Traefik

由于KubernetesIngress只能支持四层的IP:Port转发,所以我们需要使用Traefik来代替Ingress

该部分参考 Kubernetes 部署 Ingress 控制器 Traefik v2.2 后运行成功后,总结得出。

创建 CRD 资源

Traefik v2.0版本后,开始使用CRD(Custom Resource Definition)来完成路由配置等,所以需要提前创建CRD资源。

traefik/k8s/k8s-crd-traefik.yaml

## IngressRoute
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  namespace: go-micro
  name: ingressroutes.traefik.containo.us
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRoute
    plural: ingressroutes
    singular: ingressroute
---
## IngressRouteTCP
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  namespace: go-micro
  name: ingressroutetcps.traefik.containo.us
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRouteTCP
    plural: ingressroutetcps
    singular: ingressroutetcp
---
## Middleware
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  namespace: go-micro
  name: middlewares.traefik.containo.us
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: Middleware
    plural: middlewares
    singular: middleware
---
## TLSOption
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  namespace: go-micro
  name: tlsoptions.traefik.containo.us
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TLSOption
    plural: tlsoptions
    singular: tlsoption
---
## TraefikService
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  namespace: go-micro
  name: traefikservices.traefik.containo.us
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TraefikService
    plural: traefikservices
    singular: traefikservice
---
## TLSStore
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  namespace: go-micro
  name: tlsstores.traefik.containo.us
spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TLSStore
    plural: tlsstores
    singular: tlsstore
  scope: Namespaced
---
## IngressRouteUDP
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  namespace: go-micro
  name: ingressrouteudps.traefik.containo.us
spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRouteUDP
    plural: ingressrouteudps
    singular: ingressrouteudp
  scope: Namespaced

执行

kubectl create -f traefik/k8s/k8s-crd-traefik.yaml

创建 RBAC 权限

traefik/k8s/k8s-rbac-traefik.yaml

## ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: go-micro
  name: traefik-ingress-services
---
## ClusterRole
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: go-micro
  name: traefik-ingress-controller
rules:
  - apiGroups: [""]
    resources: ["services","endpoints","secrets"]
    verbs: ["get","list","watch"]
  - apiGroups: ["extensions"]
    resources: ["ingresses"]
    verbs: ["get","list","watch"]
  - apiGroups: ["extensions"]
    resources: ["ingresses/status"]
    verbs: ["update"]
  - apiGroups: ["traefik.containo.us"]
    resources: ["middlewares","ingressroutes","ingressroutetcps","tlsoptions","ingressrouteudps","traefikservices","tlsstores"]
    verbs: ["get","list","watch"]
---
## ClusterRoleBinding
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: go-micro
  name: traefik-ingress-controller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: traefik-ingress-controller
subjects:
  - kind: ServiceAccount
    name: traefik-ingress-services
    namespace: go-micro

执行

kubectl create -f traefik/k8s/k8s-rbac-traefik.yml

创建 Traefik 配置文件

下面配置中可以通过配置kubernetesCRDkubernetesIngress两项参数,让Traefik支持CRDIngress两种路由方式。
traefik/k8s/k8s-config-traefik.yml

kind: ConfigMap
apiVersion: v1
metadata:
  name: traefik-config
  namespace: go-micro
data:
  traefik.yaml: |-
    ping: ""                    ## 启用 Ping
    serversTransport:
      insecureSkipVerify: true  ## Traefik 忽略验证代理服务的 TLS 证书
    api:
      insecure: true            ## 允许 HTTP 方式访问 API
      dashboard: true           ## 启用 Dashboard
      debug: true              ## 启用 Debug 调试模式
    metrics:
      prometheus: ""            ## 配置 Prometheus 监控指标数据,并使用默认配置
    entryPoints:
      web:
        address: ":80"          ## 配置 80 端口,并设置入口名称为 web
      websecure:
        address: ":443"         ## 配置 443 端口,并设置入口名称为 websecure
    providers:
      kubernetesCRD: ""         ## 启用 Kubernetes CRD 方式来配置路由规则
      kubernetesIngress: ""     ## 启动 Kubernetes Ingress 方式来配置路由规则
    log:
      filePath: ""              ## 设置调试日志文件存储路径,如果为空则输出到控制台
      level: error              ## 设置调试日志级别
      format: json              ## 设置调试日志格式
    accessLog:
      filePath: ""              ## 设置访问日志文件存储路径,如果为空则输出到控制台
      format: json              ## 设置访问调试日志格式
      bufferingSize: 0          ## 设置访问日志缓存行数
      filters:
        #statusCodes: ["200"]   ## 设置只保留指定状态码范围内的访问日志
        retryAttempts: true     ## 设置代理访问重试失败时,保留访问日志
        minDuration: 20         ## 设置保留请求时间超过指定持续时间的访问日志
      fields:                   ## 设置访问日志中的字段是否保留(keep 保留、drop 不保留)
        defaultMode: keep       ## 设置默认保留访问日志字段
        names:                  ## 针对访问日志特别字段特别配置保留模式
          ClientUsername: drop
        headers:                ## 设置 Header 中字段是否保留
          defaultMode: keep     ## 设置默认保留 Header 中字段
          names:                ## 针对 Header 中特别字段特别配置保留模式
            User-Agent: redact
            Authorization: drop
            Content-Type: keep
    #tracing:                     ## 链路追踪配置,支持 zipkin、datadog、jaeger、instana、haystack 等
    #  serviceName:               ## 设置服务名称(在链路追踪端收集后显示的服务名)
    #  zipkin:                    ## zipkin配置
    #    sameSpan: true           ## 是否启用 Zipkin SameSpan RPC 类型追踪方式
    #    id128Bit: true           ## 是否启用 Zipkin 128bit 的跟踪 ID
    #    sampleRate: 0.1          ## 设置链路日志采样率(可以配置0.01.0之间的值)
    #    httpEndpoint: http://localhost:9411/api/v2/spans     ## 配置 Zipkin Server 端点

执行

kubectl create -f traefik/k8s/k8s-config-traefik.yml

部署 Traefik

下面将用DaemonSet方式部署Traefik,便于在多服务器间扩展,用hostport方式绑定服务器80443端口,方便流量通过物理机进入Kubernetes内部。

traefik/k8s/k8s-pod-traefik.yml

apiVersion: v1
kind: Service # 这个svc主要用来跟rule转发规则里转到至的端口相对应
metadata:
  namespace: go-micro
  name: traefik
spec:
  ports:
    - name: web
      port: 80
    - name: websecure
      port: 443
    - name: admin
      port: 8080
  selector:
    app: traefik
---
apiVersion: apps/v1
kind: DaemonSet # DaemonSet保证在每个Node上都运行一个Pod,如果 新增一个Node,这个Pod也会运行在新增的Node上,如果删除这个DadmonSet,就会清除它所创建的Pod。
metadata:
  name: traefik-ingress-controller
  namespace: go-micro
  labels:
    app: traefik
spec:
  selector:
    matchLabels:
      app: traefik
  template:
    metadata:
      name: traefik
      labels:
        app: traefik
    spec:
      serviceAccountName: traefik-ingress-services
      terminationGracePeriodSeconds: 1
      hostNetwork: true ## 将容器端口绑定所在服务器端口
      containers:
        - image: traefik:v2.2.1
          name: traefik-ingress-lb
          ports:
            - name: web
              containerPort: 80
            - name: websecure
              containerPort: 443
            - name: admin
              containerPort: 8080  ## Traefik Dashboard 端口
          resources:
            limits:
              cpu: 2000m
              memory: 1024Mi
            requests:
              cpu: 1000m
              memory: 1024Mi
          securityContext:
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
          args:
            - --configfile=/config/traefik.yaml
          volumeMounts:
            - mountPath: "/config"
              name: "config"
          readinessProbe:
            httpGet:
              path: /ping
              port: 8080
            failureThreshold: 3
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 5
          livenessProbe:
            httpGet:
              path: /ping
              port: 8080
            failureThreshold: 3
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 5
      volumes:
        - name: config
          configMap:
            name: traefik-config

执行

kubectl create -f traefik/k8s/k8s-pod-traefik.yml

注意

DaemonSet保证在每个Node都运行一个Pod,如果 新增一个Node,这个Pod也会运行在新增的Node上,如果删除这个DadmonSet,就会清除它所创建的Pod

如果想指定只能在哪些node上创建traefik,则需要提前指定Label,这样当程序部署时会自动调度到设置Label的节点上。

# 格式:kubectl label nodes [节点名] [key=value]
kubectl label nodes docker-desktop IngressProxy=true

# 查看节点是否设置 Label 成功
kubectl get nodes --show-labels

同时,需要修改 traefik/k8s/k8s-pod-traefik.yml

      volumes:
        - name: config
          configMap:
            name: traefik-config 
      # 以上是已经存在的设置,下面为要添加的设置
      tolerations:              # 设置容忍所有污点,防止节点被设置污点
        - operator: "Exists"
      nodeSelector:             # 设置node筛选器,在特定label的节点上启动
        IngressProxy: "true"

我懒就没做了。。。

配置路由规则

Traefik 应用已经部署完成,但是想让外部访问Kubernetes内部服务,还需要配置路由规则,上面部署Traefik时开启了Traefik Dashboard,这是Traefik提供的视图看板,所以,首先配置基于HTTPTraefik Dashboard路由规则,使外部能够访问 Traefik Dashboard。这里使用CRD进行演示。

想使用Ingress或者加上HTTPS认证,请参考这篇文章

使用 CRD 方式创建路由规则可言参考 Traefik 文档 Kubernetes IngressRoute

traefik/k8s/k8s-crd-router-traefik.yml

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-dashboard-route
  namespace: go-micro
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`traefik.guaosi.com`)
      kind: Rule
      services:
        - name: traefik # svc的名称
          port: 8080 # cluster 访问
    - match: Host(`apigw.guaosi.com`)
      kind: Rule
      services:
        - name: svc-apigw # svc的名称
          port: 8091 # cluster 访问

执行

kubectl create -f traefik/k8s/k8s-crd-router-traefik.yml

配置 Host 文件

客户端想通过域名访问服务,必须要进行DNS 解析,由于这里没有DNS服务器进行域名解析,所以修改hosts文件将Traefikapigw所在节点服务器的IP和自定义Host绑定,。打开电脑的Hosts配置文件,往其加入下面配置:

192.168.1.200  traefik.guaosi.com
192.168.1.200  apigw.guaosi.com

验证

Dashboard

打开浏览器输入地址:traefik.guaosi.com ,即可打开Traefik Dashboard

服务

> curl -X POST -d "username=guaosi&password=guaosi" http://apigw.guaosi.com/account/register

{"code":0,"message":""}

代码仓库

最终的代码和部署文件,已经传至github,欢迎star。

github.com/guaosi/go-micro-build

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~