吾八哥博客

您现在的位置是:首页 > 云原生 > Kubernetes > 正文

Kubernetes

吾八哥学k8s(十):kubernetes里Service和Ingress

吾八哥2021-05-15Kubernetes23736

在kubernetes里我们的服务通常都是有多个Pod的,那么不同的服务之间如何通信呢?如果是用Pod的IP来进行,那么当服务动态扩缩容或者Pod发版重建的时候,Pod的IP地址也是会变化的,这个时候用IP访问就变得极其复杂了。kubernetes引用了Service来解决这种问题,Service主要用于Pod之间的通信,Service可以通过Label Selector映射到一组Pod上来对外提供服务。而Ingress则是为集群中的服务提供了入口,可以提供负载均衡、SSL 终结和基于名称的虚拟托管。Ingress公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由,流量路由由 Ingress 资源上定义的规则控制。流量先到 ingress再到service最后到Pod上,下面是一个将所有流量都发送到同一 Service 的简单 Ingress 示例:

1621085735285.jpg

创建测试服务

首先我们创建一个用于测试Service的Deployment,yaml文件如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80

执行如下命令创建测试的deployment,并且等待服务器启动完成:

kubectl apply -f my-nginx.yaml
kubectl rollout status deploy my-nginx

查看运行的my-nginx服务相关的信息如下:

5bug.wang:~/codes/kubernetes/test$ kubectl get pods -l run=my-nginx -o wide
NAME                        READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE   READINESS GATES
my-nginx-5b56ccd65f-crslj   1/1     Running   0          2m55s   172.17.0.4   minikube   <none>           <none>
my-nginx-5b56ccd65f-vfkgf   1/1     Running   0          2m55s   172.17.0.3   minikube   <none>           <none>

这个时候可以链接到上面的pod里通过Pod的IP地址进行访问,但我们今天这里要使用Service的方式来访问。

创建Service

对于service,如下知识我们得要有所了解:

  • service是通过label selector关联到对应的pod的

  • 支持tcp和udp协议,默认是tcp协议

  • 支持暴露多个端口

  • 可以定义没有selector的Service,需手动映射Endpoints

kubernetes ServiceType支持如下几种类型:

  • ClusterIP 默认类型,只能在集群内部访问使用

  • NodePort 在集群节点上打开一个端口,此端口代理到后端的Pod,支持从集群外部访问到集群内部,格式为:NodeIP:NodePort

  • LoadBalancer 使用云厂商提供的负载均衡器公开服务

  • ExternalName 通过返回定义的CNAME别名,没有任何类型的代理(1.7+的版本支持)

下面来定义一个文件名my-nginx-svc.yaml的Service:

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    run: my-nginx

基于上面的yaml文件创建service并查看service信息:

5bug.wang:~/codes/kubernetes/test$ kubectl apply -f my-nginx-svc.yaml
service/my-nginx created
5bug.wang:~/codes/kubernetes/test$ kubectl get svc my-nginx
NAME       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
my-nginx   ClusterIP   10.105.235.228   <none>        80/TCP    22s
5bug.wang:~/codes/kubernetes/test$ kubectl describe svc my-nginx
Name:              my-nginx
Namespace:         default
Labels:            run=my-nginx
Annotations:       kubectl.kubernetes.io/last-applied-configuration:
                     {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"run":"my-nginx"},"name":"my-nginx","namespace":"default"},"spe...
Selector:          run=my-nginx
Type:              ClusterIP
IP:                10.105.235.228
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         172.17.0.3:80,172.17.0.4:80
Session Affinity:  None
Events:            <none>

上面的Endpoints里就是my-nginx服务的pod IP信息,service对关联的Pod具备服务发现能力,当pod销毁的时候会自动从Endpoints移除,有新的Pod启动的时候,会自动将IP端口信息加到Endpoints里。在pod内部可以通过DNS方式进行访问service,规则为:http://{ServiceName}.{NameSpace}.svc,例如:http://my-nginx.default.svc

创建Ingress

my-nginx-ingress.yaml文件内容如下:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-nginx-ingress
  annotations:
    # use the shared ingress-nginx
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: www.5bug.wang
    http:
      paths:
      - path: /
        backend:
          serviceName: my-nginx
          servicePort: 80

说明如下:

kubernetes.io/ingress.class: "nginx":Nginx Ingress Controller 根据该注解自动发现 Ingress

rules的定义:

  • host 可选,配置对应的域名

  • path 流量访问匹配路径

  • backend 描述 serviceName和servicePort

  • 支持绑定多个域名

在使用ingress里指定的域名访问服务之前,需要先将域名解析到集群ingress节点上,否则是访问不通的。