首页 > 其他分享 >API对象--Service(chrono《kubernetes入门实战课》笔记整理)

API对象--Service(chrono《kubernetes入门实战课》笔记整理)

时间:2023-01-30 20:47:12浏览次数:33  
标签:Service kubernetes chrono IP 端口 pod ngx 80

 

【概念解说】

当pod被实例化出来,如果运行 一段时间会销毁,虽然deployment和ds会注意管理和维护pod的数目,但是pod销毁后再重建,ip会发生变化,这对于服务来说,是很麻烦的。所以需要有一个中间层来屏蔽后端的这些变化,为前端提供一个稳定的环境。大家要访问服务的时候,都是先访问这个中间层,只要它不改变ip,那么我们访问服务的时候,就永远只要访问这个IP即可。另外,这个中间层收了流量,肯定需要转发出去,如果可以自动进行负载均衡,就再好不过了,比如像LVS,但是这不是云原生的,所以Kubernetes 又专门定义了一个新的对象:Service,在集群内部,做这个中间层,并负责负载均衡。

 

 

 客户只用访问serveice的固定IP,service会根据iptables来转发请求,这个iptables,是每个节点的kube-proxy组件自动维护的。

【YAML描述】

service创建YAML的方式,为kubectl expose,这个命令同样适用于创建pod,deployment,daemonset的YAML。

apiVersion: v1
kind: Service
metadata:
  name: xxx-svc

使用 kubectl expose 指令时还需要用参数 --port 和 --target-port 分别指定映射端口和容器端口,而 Service 自己的 IP 地址和后端 Pod 的 IP 地址可以自动生成。

export out="--dry-run=client -o yaml"
kubectl expose deploy ngx-dep --port=80 --target-port=80 $out

如下是一个service YAML示例:

apiVersion: v1
kind: Service
metadata:
  name: ngx-svc
  
spec:
  selector:
    app: ngx-dep
    
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP

1)selector:用来过滤出要代理的那些 Pod。因为我们指定要代理ngx-dep这个 Deployment,所以 Kubernetes 就为我们自动填上了 ngx-dep 的标签,会选择这个 Deployment 对象部署的所有 Pod;

2)ports:分别代表外部端口、内部端口和使用的协议。

 

 

 【如何使用】

1、创建一个configmap的YAML文件cm.yml,定义一个nginx的配置片段,输出服务器的地址、主机名、请求的URL等信息。kubectl apply -f cm.yml;

apiVersion: v1
kind: ConfigMap
metadata:
  name: ngx-conf

data:
  default.conf: |
    server {
      listen 80;
      location / {
        default_type text/plain;
        return 200
          'srv : $server_addr:$server_port\nhost: $hostname\nuri : $request_method $host $request_uri\ndate: $time_iso8601\n';
      }
    }

2、将cm注入到deployment中:创建一个deployment的YAML文件deployment.yml,在“template.volumes”里定义存储卷,再用“volumeMounts”把配置文件加载进 Nginx 容器里。kubectl apply -f deployment.yml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ngx-dep

spec:
  replicas: 2
  selector:
    matchLabels:
      app: ngx-dep

  template:
    metadata:
      labels:
        app: ngx-dep
    spec:
      volumes:
      - name: ngx-conf-vol
        configMap:
          name: ngx-conf

      containers:
      - image: nginx:alpine
        name: nginx
        ports:
        - containerPort: 80

        volumeMounts:
        - mountPath: /etc/nginx/conf.d
          name: ngx-conf-vol

3、使用svc.yml创建service对象:创建一个svc的YAML文件svc.yml,kubectl apply后,使用get svc查看状态。可以看到,Kubernetes 为 Service 对象自动分配了一个 IP 地址“10.103.92.97”,这个地址段是独立于 Pod 地址段的。而且 Service 对象的 IP 地址还有一个特点,它是一个“虚地址”,不存在实体,只能用来转发流量。

apiVersion: v1
kind: Service
metadata:
  name: ngx-svc
  
spec:
  selector:
    app: ngx-dep
    
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP

 

 

 4、查看service对象代理了哪些后端的pod。截图里显示 Service 对象管理了两个 endpoint,分别是10.244.1.15:80和10.244.1.16:80,与 Service、Deployment 的定义相符。进入其中一个pod,curl代理ip10.103.92.97,看到返回的信息中,Service 确实用一个静态 IP :10.103.92.97,代理了两个 Pod 的动态 IP 地址。

 

 

 

 5、delete一个pod,ip应该会变化,之后我们重复第四步的操作

 

 6、如果ping 10.103.92.97,是ping不通的,因为这是一个虚ip,仅仅有从来做流量转发用的,ping它是不会回reply包的,所以不会ping通的。

【一点扩展】

service这个工作原理,是不是很容易让我们想到url访问的时候,我们也是输入一个域名,然后这个域名会有很多A记录,让我们最终可以解析了这个域名,进而和这个ip进行真实的业务交互。所以service提供的这个虚ip,可不可以也是个域名呢?毕竟文字肯定要比数字好记住。这里有一个新的概念:namespace(ns)。使用kubectl get ns可以看到当前集群里有哪些ns。

 

 其中,有一个默认的ns,叫default,如果不显式指定,API对象都会在这个default ns里。其他的ns也都有各自的用途,比如kube-system,就有apiserver,etcd等核心组件的pod。而service的域名形式就是:对象.名字空间.svc.cluster.local,很多时候我们也可以省略为:对象.名字空间,甚至简化为:对象名。

我们再次进入上面的ngx-dep pod,curl一下这个域名:ngx-svc,同样可以访问到。即,我们可以通过域名的方式,访问后端服务。(Kubernetes 也为每个 Pod 分配了域名,形式是“IP 地址. 名字空间.pod.cluster.local”,但需要把 IP 地址里的 . 改成 - 。比如地址 10.10.1.87,它对应的域名就是 10-10-1-87.default.pod。)

 

 【service如何对外暴露服务】

Service 对象有一个关键字段“type”,表示 Service 是哪种类型的负载均衡。前面我们看到的用法都是对集群内部 Pod 的负载均衡,所以这个字段的值就是默认的“ClusterIP”,Service 的静态 IP 地址只能在集群内访问。除了“ClusterIP”,Service 还支持其他三种类型,分别是“ExternalName”“LoadBalancer”“NodePort”。不过前两种类型一般由云服务商提供,我们的实验环境用不到,所以接下来就重点看“NodePort”这个类型。

如果我们在使用命令 kubectl expose 的时候加上参数 --type=NodePort,或者在 YAML 里添加字段 type:NodePort,那么 Service 除了会对后端的 Pod 做负载均衡之外,还会在集群里的每个节点上创建一个独立的端口,用这个端口对外提供服务,这也正是“NodePort”这个名字的由来。get svc看到“TYPE”变成了“NodePort”,而在“PORT”列里的端口信息也不一样,除了集群内部使用的“80”端口,还多出了一个“32135”端口,这就是 Kubernetes 在节点上为 Service 创建的专用映射端口。

实验一下:访问我们worker1 ip的32135端口,看看是否可以访问到ngx-dep这两个pod的服务。红框中看到,访问到的pod信息是正确的。 不过,Kubernetes 为了避免端口冲突,默认只在“30000~32767”这个范围内随机分配,只有 2000 多个可以使用,所以可能不够用。另外登录master和worker,netstat会看到,原来k8s集群里的每个节点都开放了32135端口,然后通过kube-proxy路由到最终的后端服务,如果业务量大,这无疑也增加了网络通信的成本。但 NodePort 仍然是 Kubernetes 对外提供服务的一种简单易行的方式,在其他更好的方式出现之前,我们也只能使用它。

 

标签:Service,kubernetes,chrono,IP,端口,pod,ngx,80
From: https://www.cnblogs.com/1234roro/p/17025156.html

相关文章