说说Kubernetes是怎么实现服务发现的

标签: kubernetes 服务 发现 | 发表时间:2020-02-24 03:04 | 作者:fredal
出处:https://juejin.im/welcome/backend

我们来说说 kubernetes 的服务发现。那么首先这个大前提是同主机通信以及跨主机通信都是 ok 的,即同一 kubernetes 集群中各个 pod 都是互通的。这点是由更底层的方案实现,包括 docker0/CNI 网桥、flannel vxlan/host-gw 模式等,在此篇就不展开讲了。

在各 pod 都互通的前提下,我们可以通过访问 podIp 来调用 pod 上的资源,那么离服务发现还有多少距离呢?首先 Pod 的 IP 不是固定的,另一方面我们访问一组 Pod 实例的时候往往会有负载均衡的需求,那么 service 对象就是用来解决此类问题的。

集群内通信

endPoints

service 首先解决的是集群内通信的需求,首先我们编写一个普通的 deployment:

  apiVersion: apps/v1
kind: Deployment
metadata:
  name: hostnames
spec:
  selector:
    matchLabels:
      app: hostnames
  replicas: 3
  template:
    metadata:
      labels:
        app: hostnames
    spec:
      containers:
        - name: hostnames
          image: mirrorgooglecontainers/serve_hostname
          ports:
            - containerPort: 9376
              protocol: TCP
复制代码

这个应用干的事儿就是访问它是返回自己的 hostname,并且每个 pod 都带上了 app 为 hostnames 的标签。

那么我们为这些 pod 编写一个普通的 service:

  apiVersion: v1
kind: Service
metadata:
  name: hostnames
spec:
  selector:
    app: hostnames
  ports:
    - name: default
      protocol: TCP
      port: 80
      targetPort: 9376
复制代码

可以看到 service 通过 selector 选择 了带相应的标签 pod,而这些被选中的 pod,成为 endpoints,我们可以试一下:

   ~/cloud/k8s kubectl get ep hostnames
NAME        ENDPOINTS
hostnames   172.28.21.66:9376,172.28.29.52:9376,172.28.70.13:9376
复制代码

当某一个 pod 出现问题,不处于 running 状态或者 readinessProbe 未通过时,endpoints 列表会将其摘除。

clusterIp

以上我们有了 service 和 endpoints,而默认创建 service 的类型是 clusterIp 类型,我们查看一下之前创建的 service:

   ~ kubectl get svc hostnames
NAME        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
hostnames   ClusterIP   10.212.8.127           80/TCP    8m2s
复制代码

我们看到 cluster-ip 是 10.212.8.127,那么我们此时可以在 kubernetes 集群内通过这个地址访问到 endpoints 列表里的任意 pod:

  sh-4.2# curl 10.212.8.127
hostnames-8548b869d7-9qk6b
sh-4.2# curl 10.212.8.127
hostnames-8548b869d7-wzksp
sh-4.2# curl 10.212.8.127
hostnames-8548b869d7-bvlw8
复制代码

访问了三次 clusterIp 地址,返回了三个不同的 hostname,我们意识到 clusterIp 模式的 service 自动对请求做了 round robin 形式的负载均衡。

对于此时 clusterIp 模式 serivice 来说,它有一个 A 记录是 service-name.namespace-name.svc.cluster.local,指向 clusterIp 地址:

  sh-4.2# nslookup hostnames.coops-dev.svc.cluster.local
Server:10.212.0.2
Address:10.212.0.2#53

Name:hostnames.coops-dev.svc.cluster.local
Address: 10.212.8.127
复制代码

理所当然我们通过此 A 记录去访问得到的效果一样:

  sh-4.2# curl hostnames.coops-dev.svc.cluster.local
hostnames-8548b869d7-wzksp
复制代码

那对 pod 来说它的 A 记录是啥呢,我们可以看一下:

  sh-4.2# nslookup 172.28.21.66
66.21.28.172.in-addr.arpaname = 172-28-21-66.hostnames.coops-dev.svc.cluster.local.
复制代码

headless service

service 的 cluserIp 默认是 k8s 自动分配的,当然也可以自己设置,当我们将 clusterIp 设置成 none 的时候,它就变成了 headless service。

headless service 一般配合 statefulSet 使用。statefulSet 是一种有状态应用的容器编排方式,其核心思想是给予 pod 指定的编号名称,从而让 pod 有一个不变的唯一网络标识码。那这么说来,使用 cluserIp 负载均衡访问 pod 的方式显然是行不通了,因为我们渴望通过某个标识直接访问到 pod 本身,而不是一个虚拟 vip。

这个时候我们其实可以借助 dns,每个 pod 都会有一条 A 记录 pod-name.service-name.namespace-name.svc.cluster.local指向 podIp,我们可以通过这条 A 记录直接访问到 pod。

我们编写相应的 statefulSet 和 service 来看一下:

  ---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: hostnames
spec:
  serviceName: "hostnames"
  selector:
    matchLabels:
      app: hostnames
  replicas: 3
  template:
    metadata:
      labels:
        app: hostnames
    spec:
      containers:
        - name: hostnames
          image: mirrorgooglecontainers/serve_hostname
          ports:
            - containerPort: 9376
              protocol: TCP

---
apiVersion: v1
kind: Service
metadata:
  name: hostnames
spec:
  selector:
    app: hostnames
  clusterIP: None
  ports:
    - name: default
      protocol: TCP
      port: 80
      targetPort: 9376

复制代码

如上,statefulSet 和 deployment 并没有什么不同,多了一个字段 spec.serviceName,这个字段的作用就是告诉 statefuleSet controller,在逻辑处理时使用 hostnames这个 service 来保证 pod 的唯一可解析性。

当你执行 apply 之后,一会你就可以看到生成了对应的 pod:

   ~ kubectl get pods -w -l app=hostnames
NAME          READY   STATUS    RESTARTS   AGE
hostnames-0   1/1     Running   0          9m54s
hostnames-1   1/1     Running   0          9m28s
hostnames-2   1/1     Running   0          9m24s
复制代码

如意料之中,这里对 pod 名称进行了递增编号,并不重复,同时这些 pod 的创建过程也是按照编号依次串行进行的。我们知道,使用 deployment 部署的 pod 名称会加上 replicaSet 名称和随机数,重启后是不断变化的。而这边使用 statefulSet 部署的 pod,虽然 podIp 仍然会变化,但名称是一直不会变的,基于此我们得以通过固定的 Dns A 记录来访问到每个 pod。

那么此时,我们来看一下 pod 的 A 记录:

  sh-4.2# nslookup hostnames-0.hostnames
Server:10.212.0.2
Address:10.212.0.2#53

Name:hostnames-0.hostnames.coops-dev.svc.cluster.local
Address: 172.28.3.57

sh-4.2# nslookup hostnames-1.hostnames
Server:10.212.0.2
Address:10.212.0.2#53

Name:hostnames-1.hostnames.coops-dev.svc.cluster.local
Address: 172.28.29.31

sh-4.2# nslookup hostnames-2.hostnames
Server:10.212.0.2
Address:10.212.0.2#53

Name:hostnames-2.hostnames.coops-dev.svc.cluster.local
Address: 172.28.23.31
复制代码

和之前的推论一致,我们可以通过 pod-name.service-name.namespace-name.svc.cluster.local这条 A 记录访问到 podIp,在同一个 namespace 中,我们可以简化为 pod-name.service-name

而这个时候,service 的 A 记录是什么呢:

  sh-4.2# nslookup hostnames
Server:10.212.0.2
Address:10.212.0.2#53

Name:hostnames.coops-dev.svc.cluster.local
Address: 172.28.29.31
Name:hostnames.coops-dev.svc.cluster.local
Address: 172.28.3.57
Name:hostnames.coops-dev.svc.cluster.local
Address: 172.28.23.31
复制代码

原来是 endpoints 列表里的一组 podIp,也就是说此时你依然可以通过 service-name.namespace-name.svc.cluster.local这条 A 记录来负载均衡地访问到后端 pod。

iptables

或多或少我们知道 kubernetes 里面的 service 是基于 kube-proxy 和 iptables 工作的。service 创建之后可以被 kube-proxy 感知到,那么它会为此在宿主机上创建对应的 iptables 规则。

以 cluserIp 模式的 service 为例,首先它会创建一条 KUBE-SERVICES规则作为入口:

  -A KUBE-SERVICES -d 10.212.8.127/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3
复制代码

这条记录的意思是:所有目的地址是 10.212.8.127 这条 cluserIp 的,都将跳转到 KUBE-SVC iptables 链处理。

那么我们来看 KUBE-SVC链都是什么:

  
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-WNBA2IHDGP2BOBGZ
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-X3P2623AGDH6CDF3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -j KUBE-SEP-57KPRZ3JQVENLNBR
复制代码

这组规则其实是用于负载均衡的,我们看到了--probability 依次是 1/3、1/2、1,由于 iptables 规则是自上而下匹配的,所以设置这些值能保证每条链匹配到的几率一样。处理完负载均衡的逻辑后,又分别将请求转发到了另外三条规则,我们来看一下:

  -A KUBE-SEP-57KPRZ3JQVENLNBR -s 172.28.21.66/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-57KPRZ3JQVENLNBR -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 172.28.21.66:9376

-A KUBE-SEP-WNBA2IHDGP2BOBGZ -s 172.28.29.52/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 172.28.29.52:9376

-A KUBE-SEP-X3P2623AGDH6CDF3 -s 172.28.70.13/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-X3P2623AGDH6CDF3 -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 172.28.70.13:9376
复制代码

可以看到 KUBE-SEP链 就是三条 DNAT 规则,并在 DNAT 之前设置了一个 0x00004000 的标志。DNAT 规则就是在 PREROUTING,即路由作用之前,将请求的目的地址和端口改为--to-destination 指定的 podIp 和端口。这样一来,我们起先访问 10.212.8.127 这个 cluserIp 的请求,就会被负载均衡到各个 pod 上。

那么 pod 重启了,podIp 变了怎么办?自然是 kube-proxy 负责监听 pod 变化以及更新维护 iptables 规则了。

而对于 headless service 来说,我们直接通过固定的 A 记录访问到了 pod,自然不需要这些 iptables 规则了。

iptables 理解起来比较简单,但实际上性能并不好。可以想象,当我们的 pod 非常多时,成千上万的 iptables 规则将被创建出来,并不断刷新,会占用宿主机大量的 cpu 资源。一个行之有效的方案是基于 IPVS 模式的 service,IPVS 不需要为每个 pod 都设置 iptables 规则,而是将这些规则都放到了内核态,极大降低了维护这些规则的成本。

集群间通信

外界访问 sevice

以上我们讲了请求怎么在 kubernetes 集群内互通,主要基于 kube-dns 生成的 dns 记录以及 kube-proxy 维护的 iptables 规则。而这些信息都是作用在集群内的,那么自然我们从集群外访问不到一个具体的 service 或者 pod 了。

service 除了默认的 cluserIp 模式外,还提供了很多其他的模式,比如 nodePort 模式,就是用于解决该问题的。

  apiVersion: v1
kind: Service
metadata:
  name: hostnames
spec:
  selector:
    app: hostnames
  type: NodePort
  ports:
    - nodePort: 8477
      protocol: TCP
      port: 80
      targetPort: 9376
复制代码

我们编写了一个 nodePort 模式的 service,并且设置 nodePort 为 8477,那么意味着我们可以通过任意一台宿主机的 8477 端口访问到 hostnames 这个 sevice。

  sh-4.2# curl 10.1.6.25:8477
hostnames-8548b869d7-j5lj9
sh-4.2# curl 10.1.6.25:8477
hostnames-8548b869d7-66vnv
sh-4.2# curl 10.1.6.25:8477
hostnames-8548b869d7-szz4f
复制代码

我们随便找了一台 node 地址去访问,得到了相同的返回配方。 那么这个时候它的 iptables 规则是怎么作用的呢:

  -A KUBE-NODEPORTS -p tcp -m comment --comment "default/hostnames: nodePort" -m tcp --dport 8477 -j KUBE-SVC-67RL4FN6JRUPOJYM
复制代码

kube-proxy 在每台宿主机上都生成了如上的 iptables 规则,通过--dport 指定了端口,访问该端口的请求都会跳转到 KUBE-SVC链上, KUBE-SVC链和之前 cluserIp service 的配方一样,接下来就和访问 cluserIp service 没什么区别了。

不过还需要注意的是,在请求离开当前宿主机发往其他 node 时会对其做一次 SNAT 操作:

  
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE
复制代码

可以看到这条 postrouting 规则给即将离开主机的请求进行了一次 SNAT,判断条件为带有 0x4000 标志,这就是之前 DNAT 带的标志,从而判断请求是从 service 转发出来的,而不是普通请求。

需要做 SNAT 的原因很简单,首先这是一个外部的未经 k8s 处理的请求, 如果它访问 node1,node1 的负载均衡将其转发给 node2 上的某个 pod,这没什么问题,而这个 pod 处理完后直接返回给外部 client,那么外部 client 就很疑惑,明明自己访问的是 node1,给自己返回的确是 node2,这时往往会报错。

SNAT 的作用与 DNAT 相反,就是在请求从 node1 离开发往 node2 时,将源地址改为 node1 的地址,那么当 node2 上的 pod 返回时,会返回给 node1,然后再让 node1 返回给 client。

                client
                | ^
                | |
                v |
   node 2 <--- node 1
    | ^   SNAT
    | |   --->
    v |
 endpoints
复制代码

service 还有另外 2 种通过外界访问的方式。适用于公有云的 LoadBalancer 模式的 service,公有云 k8s 会调用 CloudProvider 在公有云上为你创建一个负载均衡服务,并且把被代理的 Pod 的 IP 地址配置给负载均衡服务做后端。另外一种是 ExternalName 模式,可以通过在 spec.externalName来指定你想要的外部访问域名,例如 hostnames.example.com,那么你访问该域名和访问 service-name.namespace-name.svc.cluser.local效果是一样的,这时候你应该知道,其实 kube-dns 为你添加了一条 cname 记录。

ingress

service 有一种类型叫作 loadBalancer,不过如果每个 service 对外都配置一个负载均衡服务,成本很高而且浪费。一般来说我们希望有一个全局的负载均衡器,通过访问不同 url,转发到不同 service 上,而这就是 ingress 的功能,ingress 可以看做是 service 的 service。

ingress 其实是对反向代理的一种抽象,相信大家已经感觉到,这玩意儿和 nginx 十分相似,实际上 ingress 是抽象层,而其实现层其中之一就支持 nginx。

我们可以部署一个 nginx ingress controller:

  $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml
复制代码

mandatory.yaml是官方维护的 ingress controller,我们看一下:

  
kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        ...
    spec:
      serviceAccountName: nginx-ingress-serviceaccount
      containers:
        - name: nginx-ingress-controller
          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.20.0
          args:
            - /nginx-ingress-controller
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx
            - --annotations-prefix=nginx.ingress.kubernetes.io
          securityContext:
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -> 33
            runAsUser: 33
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
            - name: http
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
            - name: http
              containerPort: 80
            - name: https
              containerPort: 443
复制代码

总的来说,我们定义了一个基于 nginx-ingress-controller 镜像的 pod, 而这个 pod 自身,是一个监听 ingress 对象及其代理后端 service 变化的控制器。

当一个 ingress 对象被创建时,nginx-ingress-controller 就会根据 ingress 对象里的内容,生成一份 nginx 配置文件(nginx.conf),并依此启动一个 nginx 服务。

当 ingress 对象被更新时,nginx-ingress-controller 就会更新这个配置文件。nginx-ingress-controller 还通过 nginx lua 方案实现了 nginx upstream 的动态配置。

为了让外界可以访问到这个 nginx,我们还得给它创建一个 service 来把 nginx 暴露出去:

  $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/baremetal/service-nodeport.yaml
复制代码

这里面的内容描述了一个 nodePort 类型的 service:

  
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: 80
      protocol: TCP
    - name: https
      port: 443
      targetPort: 443
      protocol: TCP
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
复制代码

可以看到这个 service 仅仅是把 nginx pod 的 80/443 端口暴露出去,完了你就可以通过宿主机 Ip 和 nodePort 端口访问到 nginx 了。

接下来我们来看 ingress 对象一般是如何编写的,我们可以参考一个 例子

  apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: cafe-ingress
spec:
  tls:
  - hosts:
    - cafe.example.com
    secretName: cafe-secret
  rules:
  - host: cafe.example.com
    http:
      paths:
      - path: /tea
        backend:
          serviceName: tea-svc
          servicePort: 80
      - path: /coffee
        backend:
          serviceName: coffee-svc
          servicePort: 80
复制代码

这个 ingress 表明我们整体的域名是 cafe.example.com,希望通过 cafe.example.com/tea访问 tea-svc这个 service,通过 cafe.example.com/coffee访问 coffee-svc这个 service。这里我们通过关键字段 spec.rules来编写转发规则。

我们可以查看到 ingress 对象的详细信息:

  
$ kubectl get ingress
NAME           HOSTS              ADDRESS   PORTS     AGE
cafe-ingress   cafe.example.com             80, 443   2h

$ kubectl describe ingress cafe-ingress
Name:             cafe-ingress
Namespace:        default
Address:
Default backend:  default-http-backend:80 ()
TLS:
  cafe-secret terminates cafe.example.com
Rules:
  Host              Path  Backends
  ----              ----  --------
  cafe.example.com
                    /tea      tea-svc:80 ()
                    /coffee   coffee-svc:80 ()
Annotations:
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  4m    nginx-ingress-controller  Ingress default/cafe-ingress
复制代码

我们之前讲了我们通过 nodePort 的方式将 nginx-ingress 暴露出去了,而这时候我们 ingress 配置又希望通过 cafe.example.com来访问到后端 pod,那么首先 cafe.example.com这个域名得指到 任意一台宿主机Ip:nodePort上,请求到达 nginx-ingress 之后再转发到各个后端 service 上。当然,暴露 nginx-ingress 的方式有很多种,除了 nodePort 外还包括 loadBalancer、hostNetWork 方式等等。

我们最后来试一下请求:

  $ curl cafe.example.com/coffee
Server name: coffee-7dbb5795f6-vglbv
$ curl cafe.example.com/tea
Server name: tea-7d57856c44-lwbnp
复制代码

可以看到 nginx ingress controller 已经为我们成功将请求转发到了对应的后端 service。而当请求没有匹配到任何一条 ingress rule 的时候,理所当然我们会得到一个 404。

至此,kubernetes 的容器网络是怎么实现服务发现的已经讲完了,而服务发现正是微服务架构中最核心的问题,解决了这个问题,那么使用 kubernetes 来实现微服务架构也就实现了一大半。

fredal.xin/kubertnetes…

相关 [kubernetes 服务 发现] 推荐:

Kubernetes中的服务发现与负载均衡

- - Feisky's Blog
Kubernetes在设计之初就充分考虑了针对容器的服务发现与负载均衡机制,提供了Service资源,并通过kube-proxy配合cloud provider来适应不同的应用场景. 随着kubernetes用户的激增,用户场景的不断丰富,又产生了一些新的负载均衡机制. 目前,kubernetes中的负载均衡大致可以分为以下几种机制,每种机制都有其特定的应用场景:.

说说Kubernetes是怎么实现服务发现的

- - 掘金后端
我们来说说 kubernetes 的服务发现. 那么首先这个大前提是同主机通信以及跨主机通信都是 ok 的,即同一 kubernetes 集群中各个 pod 都是互通的. 这点是由更底层的方案实现,包括 docker0/CNI 网桥、flannel vxlan/host-gw 模式等,在此篇就不展开讲了.

浅谈 Kubernetes 中的服务发现 | 伪架构师

- -
Kubernetes 服务发现是一个经常让我产生困惑的主题之一. 深入了解 Kubernetes 服务发现. 要了解服务发现,首先要了解背后的网络知识. 这部分内容相对浅显,如果读者熟知这一部分,完全可以跳过,直接阅读服务发现部分. 开始之前还有一个需要提醒的事情就是,为了详细描述这一过程,本文略长.

spring-cloud-kubernetes的服务发现和轮询实战(含熔断)_程序员欣宸的博客-CSDN博客

- -
本文是《spring-cloud-kubernetes实战系列》的第四篇,主要内容是在kubernetes上部署两个应用:Web-Service和Account-Service,通过spring-cloud-kubernetes提供的注册发现能力,实现Web-Service调用Account-Service提供的http服务;.

kubernetes dashboard向外网提供服务

- - 学习日志
目前新版本的 kubernetes dashboard ( https://github.com/kubernetes/dashboard)安装了后,为了安全起见,默认情况下已经不向外提供服务,只能通过. http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ 本机访问.

使用 Kubernetes Ingress 对外暴露服务

- - DockOne.io
本文主要介绍如何通过 Kubernetes Ingress 资源对象实现从外部对 Kubernetes 集群中服务的访问,介绍了 Kubernetes 对外暴露服务的多种方法、Ingress 及 Ingress Controller 的概念. Kubernetes 对外暴露服务的方法. 向 Kubernetes 集群外部暴露服务的方式有三种: nodePort,LoadBalancer 和本文要介绍的 Ingress.

Kubernetes 服务部署最佳实践(一)

- - 腾讯云容器团队
业务容器化后,如何将其部署在 K8S 上. 如果仅仅是将它跑起来,很简单,但如果是上生产,我们有许多地方是需要结合业务场景和部署环境进行方案选型和配置调优的. 比如,如何设置容器的 Request 与 Limit、如何让部署的服务做到高可用、如何配置健康检查、如何进行弹性伸缩、如何更好的进行资源调度、如何选择持久化存储、如何对外暴露服务等.

Kubernetes在微服务中的最佳实践

- - DockOne.io
你可以在网上找到许多关于如何正确构建微服务体系架构的最佳实践. 其中之一是我以前写的一篇文章 Spring Boot在微服务中的最佳实践. 我把重点放在在生产上基于Spring Boot构建的微服务应用程序应该考虑哪些方面. 我没有使用任何用于编排或管理应用程序的平台,而只是一组独立的应用程序. 在本文中,我将基于已经介绍的最佳实践,在Kubernetes平台上部署微服务,你需要注意的一些新规则和事项.

Kubernetes - 集群内容器访问集群外服务

- - 掘金后端
GitHub地址: github.com/QingyaFan/c…. 企业内部一般存在很多的微服务,在逐步容器化的过程中,会有部分服务在集群外部,未完成容器化,比如数据库,而部分已经完成容器化的依赖于这些服务的服务,过渡过程中,需要集群内部的容器访问集群外部的服务. 为了在容器化过程中,让服务不中断,就需要让Kubernetes集群内部的容器能访问集群外部的服务,怎么做到呢,在每个应用的配置文件中使用外部IP或者外部rds名字吗.

Kong 微服务网关在 Kubernetes 的实践

- - DockOne.io
译者:qianghaohao. 本文主要介绍将 Kong 微服务网关作为 Kubernetes 集群统一入口的最佳实践,之前写过一篇文章使用 Nginx Ingress Controller 作为集群统一的流量入口:使用 Kubernetes Ingress 对外暴露服务,但是相比于 Kong Ingress Controller来说,Kong 支持的功能更加强大,更适合微服务架构:.