K8S 生产实践-06-服务发现 Service

Kubernetes 中为了实现服务实例间的负载均衡和不同服务间的服务发现,创造了 Serivce 对象,同时又为从集群外部访问集群创建了 Ingress 对象。

一、服务发现

服务之间的发现、服务之间的通信是必须要考虑的问题,总结一共有三种常用的方式:

1、集群内部(集群内部该如何服务发现、服务通信)
2、集群内-》集群外
3、集群外 -》集群内

1、集群内部的访问方式:
集群内部访问,如果两个pod要相互访问,可以通过 pod ip 来访问,但这不是一个很好的方式,因为pod ip 是不稳定的,会经常变化(pod 挂了之后会重新拉取一个新的pod),这时候可以通过service 来解决该问题;

file

service可以对应多个pod,通过内部机制来实现负载均衡,只要service不被删掉,则IP 永远是不变的;

file

如果集群中布满了service,也是不够优雅的,这时候k8s提供了DNS的概念,可以通过service 的名字来访问到service,比如名字叫(SerB),这个DNS可以解析service ip(10.0.0.1),从而实现对pod的访问;

这种方案我们叫做 DNS + ClusterIP

file

还有一种方案,Pod C 有多个实例,Pod A 访问HeadlessService,会将pod C 的实例列表返回,客户端拿到实例列表后自己来确定访问。
file

2、集群内部访问集群外部的访问方式:
示例:集群内部访问集群外部的MySQL服务
file

3、集群外部访问集群内部的服务:

file

file

二、ingress

Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。

Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。

术语

为了表达更加清晰,本指南定义了以下术语:

  • 节点(Node): Kubernetes 集群中的一台工作机器,是集群的一部分。
  • 集群(Cluster): 一组运行由 Kubernetes 管理的容器化应用程序的节点。 在此示例和在大多数常见的 Kubernetes 部署环境中,集群中的节点都不在公共网络中。
  • 边缘路由器(Edge Router): 在集群中强制执行防火墙策略的路由器。可以是由云提供商管理的网关,也可以是物理硬件。
  • 集群网络(Cluster Network): 一组逻辑的或物理的连接,根据 Kubernetes 网络模型在集群内实现通信。
  • 服务(Service):Kubernetes 服务(Service), 使用标签选择器(selectors)辨认一组 Pod。 除非另有说明,否则假定服务只具有在集群网络中可路由的虚拟 IP。

Ingress 是什么?

Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。

下面是一个将所有流量都发送到同一 Service 的简单 Ingress 示例:
file

Ingress 可为 Service 提供外部可访问的 URL、负载均衡流量、终止 SSL/TLS,以及基于名称的虚拟托管。 Ingress 控制器 通常负责通过负载均衡器来实现 Ingress,尽管它也可以配置边缘路由器或其他前端来帮助处理流量。

Ingress 不会公开任意端口或协议。 将 HTTP 和 HTTPS 以外的服务公开到 Internet 时,通常使用 Service.Type=NodePort 或 Service.Type=LoadBalancer 类型的 Service。

Ingress是个什么鬼,网上资料很多(推荐官方),大家自行研究。简单来讲,就是一个负载均衡的玩意,其主要用来解决使用NodePort暴露Service的端口时Node IP会漂移的问题。同时,若大量使用NodePort暴露主机端口,管理会非常混乱。

好的解决方案就是让外界通过域名去访问Service,而无需关心其Node IP及Port。那为什么不直接使用Nginx?这是因为在K8S集群中,如果每加入一个服务,我们都在Nginx中添加一个配置,其实是一个重复性的体力活,只要是重复性的体力活,我们都应该通过技术将它干掉。

Ingress就可以解决上面的问题,其包含两个组件 Ingress ControllerIngress

Ingress
将Nginx的配置抽象成一个Ingress对象,每添加一个新的服务只需写一个新的Ingress的yaml文件即可
Ingress Controller
将新加入的Ingress转化成Nginx的配置文件并使之生效

查看监听的端口号:

netstat -ntlp | grep 80

示例:

#deploy
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-demo
spec:
  selector:
    matchLabels:
      app: tomcat-demo
  replicas: 1
  template:
    metadata:
      labels:
        app: tomcat-demo
    spec:
      containers:
      - name: tomcat-demo
        image: registry.cn-hangzhou.aliyuncs.com/liuyi01/tomcat:8.0.51-alpine
        ports:
        - containerPort: 8080
---
#service
apiVersion: v1
kind: Service
metadata:
  name: tomcat-demo
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: tomcat-demo

---
#ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: tomcat-demo
spec:
  rules:
  - host: tomcat.mooc.com
    http:
      paths:
      - path: /
        backend:
          serviceName: tomcat-demo
          servicePort: 80

file

:set paste # 复制粘贴,样式不变

file

创建Pod:

[hemei@master test]$ kubectl create -f ingress-demo.yaml 
deployment.apps/tomcat-demo created
service/tomcat-demo created
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions/tomcat-demo created
[hemei@master test]$ 

查看起的Pod:

[hemei@master test]$ kubectl get pod -o wide
NAME                                               READY   STATUS    RESTARTS   AGE     IP              NODE    NOMINATED NODE   READINESS GATES
nfs-subdir-external-provisioner-6dcc58bb4b-8fc84   1/1     Running   11         150d    172.16.123.39   work2   <none>           <none>
tomcat-demo-54cbbcffdb-2hn5h                       1/1     Running   0          2m12s   172.16.123.32   work2   <none>           <none>

三、实践

ingress-nginx 安装

这里采用 nginx-ingress-controller:0.30.0

[root@hombd03 ~]]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml

拉取镜像:

[root@hombd03 ~]# cat mandatory.yaml | grep image
          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0

所有节点下载 quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0

[root@hombd03 ~]# docker pull quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0

创建:

[root@centos03 k8s]# kubectl apply -f mandatory.yaml
Warning: resource namespaces/ingress-nginx is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
namespace/ingress-nginx configured
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created

查看pod:

[root@hombd03 ~]# kubectl get pod -n ingress-nginx

NAME                                        READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-54b86f8f7b-tblw7   0/1     Running   0          24s

可以看到上边的已经安装好了,然后进行ingress service 服务暴露;

ingress service 服务暴露

1、先查看节点work(node2、node3,这里需要安装在worker节点,而非master节点上) 80和 443端口占用情况

[root@hombd04 ~]# netstat -ntlp | grep 80
tcp        0      0 0.0.0.0:8010            0.0.0.0:*               LISTEN      4595/java           
tcp        0      0 192.168.1.124:2380      0.0.0.0:*               LISTEN      10988/etcd          
tcp6       0      0 :::10252                :::*                    LISTEN      8031/kube-controlle 
tcp6       0      0 :::45804                :::*                    LISTEN      20523/java          
tcp6       0      0 :::10257                :::*                    LISTEN      8031/kube-controlle 
[root@homaybd04 ~]# netstat -ntlp | grep 443
tcp6       0      0 :::6443                 :::*                    LISTEN      7213/kube-apiserver 
[root@hombd04 ~]# 

如何让 pod 运行在指定的节点上?可以在yaml文件指定的节点标签,先查看node节点:

[root@hombd03 ingress-nginx]# kubectl get nodes
NAME        STATUS   ROLES    AGE   VERSION
hombd04   Ready    <none>   14d   v1.20.2
hombd05   Ready    <none>   14d   v1.20.2
[root@hombd03 ingress-nginx]# 

然后给节点打标签,这里给 hombd04 节点打标签:

[root@hombd03 ingress-nginx]# kubectl label node homaybd04 app=ingress
node/hombd04 labeled

然后修改 mandatory.yaml 文件,网络为:hostNetwork

默认的配置:
file

修改后的:
file

重新部署该文件mandatory.yaml

[root@hombd03 ingress-nginx]# kubectl apply -f mandatory.yaml 
namespace/ingress-nginx unchanged
configmap/nginx-configuration unchanged
configmap/tcp-services unchanged

查看部署的节点:

[root@hombd03 ingress-nginx]# kubectl get pod -n ingress-nginx -o wide
NAME                                        READY   STATUS             RESTARTS   AGE   IP                NODE        NOMINATED NODE   READINESS GATES
nginx-ingress-controller-84787756d5-zqpx2   1/1     Running            0          88s   192.168.1.124     homaybd04   <none>           <none>
[root@hombd03 ingress-nginx]# 

可以看到已经部署到指定的 hombd04 worker 节点上了。

然后再去 hombd04 节点看 80 和 443 端口是否存在:

[root@hombd04 ~]# netstat -nltp | grep 80
tcp        0      0 0.0.0.0:8010            0.0.0.0:*               LISTEN      4595/java           
tcp        0      0 192.168.1.124:2380      0.0.0.0:*               LISTEN      10988/etcd          
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      20315/nginx: master 
tcp6       0      0 :::10252                :::*                    LISTEN      8031/kube-controlle 
tcp6       0      0 :::45804                :::*                    LISTEN      20523/java          
tcp6       0      0 :::80                   :::*                    LISTEN      20315/nginx: master 
tcp6       0      0 :::10257                :::*                    LISTEN      8031/kube-controlle 
[root@homaybd04 ~]# netstat -nltp | grep 443
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      20315/nginx: master 
tcp6       0      0 :::6443                 :::*                    LISTEN      7213/kube-apiserver 
tcp6       0      0 :::443                  :::*                    LISTEN      20315/nginx: master 
[root@hombd04 ~]# 

测试案例 ingress-demo.yaml

#deploy
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-demo
spec:
  selector:
    matchLabels:
      app: tomcat-demo
  replicas: 1
  template:
    metadata:
      labels:
        app: tomcat-demo
    spec:
      containers:
      - name: tomcat-demo
        image: registry.cn-hangzhou.aliyuncs.com/liuyi01/tomcat:8.0.51-alpine
        ports:
        - containerPort: 8080
---
#service
apiVersion: v1
kind: Service
metadata:
  name: tomcat-demo
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: tomcat-demo

---
#ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: tomcat-demo
spec:
  rules:
  - host: tomcat.mooc.com
    http:
      paths:
      - path: /
        backend:
          serviceName: tomcat-demo
          servicePort: 80

部署:

[root@homaybd03 ingress-nginx]# kubectl create -f ingress-demo.yaml 
deployment.apps/tomcat-demo created
service/tomcat-demo created

如果拉取不下来,则单独拉取:

[root@homaybd03 ~]# docker pull registry.cn-hangzhou.aliyuncs.com/liuyi01/tomcat:8.0.51-alpine
8.0.51-alpine: Pulling from liuyi01/tomcat

查看部署的 tomcat-demo 服务:

[root@homaybd03 ingress-nginx]# kubectl get pod -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP                NODE        NOMINATED NODE   READINESS GATES
nginx                          1/1     Running   1          14d   192.200.72.199    homaybd05   <none>           <none>
nginx-ds-87flg                 1/1     Running   1          14d   192.200.245.133   homaybd04   <none>           <none>
nginx-ds-j7mqr                 1/1     Running   1          14d   192.200.72.198    homaybd05   <none>           <none>
tomcat-demo-54cbbcffdb-dgct2   1/1     Running   0          56s   192.200.72.202    homaybd05   <none>           <none>

然后修改配置,因为我们的nginx-ingrees 部署在 homaybd04 节点,所以,需要改为该IP配置:

sudo vi /etc/hosts

# 域名配置
192.168.1.124 tomcat.mooc.com
192.168.1.124 api.mooc.com

然后在浏览器访问 http://tomcat.mooc.com/ ,可以看到已经部署成功了:
file

单独下载镜像

root@homaybd03 ingress-nginx]# pwd
/root/ingress-nginx
[root@homaybd03 ingress-nginx]# grep image mandatory.yaml 
          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
[root@homaybd03 ingress-nginx]# 

然后查看该镜像是否下载到本地:

[root@homaybd03 ingress-nginx]# grep image mandatory.yaml 
          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
[root@homaybd03 ingress-nginx]# docker pull quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
0.30.0: Pulling from kubernetes-ingress-controller/nginx-ingress-controller
Digest: sha256:b312c91d0de688a21075078982b5e3a48b13b46eda4df743317d3059fc3ca0d9
Status: Image is up to date for quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
[root@homaybd03 ingress-nginx]# 

如果镜像下载不下来,则需要再国内镜像库下载:

docker pull registry.cn-hangzhou.aliyuncs.com/liuyi01/nginx-ingress-controller:0.30.0

查看部署的服务:

[root@hombd03 ~]# kubectl get all -n ingress-nginx
NAME                                            READY   STATUS             RESTARTS   AGE
pod/ingress-nginx-admission-create-q8947        0/1     ImagePullBackOff   0          11d
pod/ingress-nginx-admission-patch-n8cj9         0/1     ImagePullBackOff   0          11d
pod/nginx-ingress-controller-84787756d5-zqpx2   1/1     Running            0          11d

NAME                                         TYPE           CLUSTER-IP        EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx-controller             LoadBalancer   192.233.205.222   <pending>     80:30720/TCP,443:30714/TCP   11d
service/ingress-nginx-controller-admission   ClusterIP      192.233.236.91    <none>        443/TCP                      11d

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-ingress-controller   1/1     1            1           11d

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-ingress-controller-54b86f8f7b   0         0         0       11d
replicaset.apps/nginx-ingress-controller-84787756d5   1         1         1       11d

NAME                                       COMPLETIONS   DURATION   AGE
job.batch/ingress-nginx-admission-create   0/1           11d        11d
job.batch/ingress-nginx-admission-patch    0/1           11d        11d
[root@hombd03 ~]# 

相关文章:
k8s官网|Ingress
84-K8S 入门操作之 Pod、Controller、Service、Ingress 等核心概念
Ingress Installation Guide
K8S ingress 实践
imooc|6-6-部署ingress-nginx

为者常成,行者常至