kubernetes-Service

1、前言

我们不应该期望Kubernetes Pod是健壮的,而是要假设Pod中的容器很可能因为各种原因发生故障而死掉。Deployment等Controller会通过动态创建和销毁Pod来保证应用整体的健壮性。换句话说,Pod是脆弱的,但应用是健壮的。每个Pod都有自己的IP地址。当Controller用新Pod替代发生故障的Pod时,新Pod会分配到新的IP地址。这样就产生了一个问题:如果一组Pod对外提供服务(比如HTTP),它们的IP很有可能发生变化,那么客户端如何找到并访问这个服务呢?Kubernetes给出的解决方案是Service。

2、基本语法

2.1 Service yaml

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: httpd-demo-1
  namespace: test
  labels:
    app: httpd-demo
spec:
  selector:
    app: httpd-demo
  ports:
  - port: 80
    protocol: TCP

2.2 关键字段

  • selector:选择器。selector是一个键值对,用于指定Service要代理的Pod的标签。Service会自动检测满足selector条件的Pod,并将流量转发给它们。
  • ports:用于定义Service所使用的端口。这个字段是一个对象,其中包含多个字段,最常用的两个字段是port和targetPort

2.3 port、nodePort、targetPort、containerPort字段说明

port是暴露在cluster ip上的端口,:port提供了集群内部客户端访问service的入口,即clusterIP:port。

nodePort提供了集群外部客户端访问service的一种方式,:nodePort提供了集群外部客户端访问service的端口,即nodeIP:nodePort提供了外部流量访问k8s集群中service的入口。

targetPort是pod上的端口,从port/nodePort上来的数据,经过kube-proxy流入到后端pod的targetPort上,最后进入容器。

containerPort是在pod控制器中定义的、pod中的容器需要暴露的端口。

3、Service 类型

3.1 ClusterIP

Service通过Cluster内部的IP对外提供服务,只有Cluster内的节点和Pod可访问,这是默认的Service类型。

3.2 NodePort

将Service通过指定的Node上的端口暴露给外部,访问任意一个 NodeIP:nodePort都将路由到ClusterIP。

端口范围:30000-32767,可以不指定,k8s会生成一个nodePort

3.3 LoadBalancer

使用云平台的负载均衡器向外部公开 Service。Kubernetes 不直接提供负载均衡组件; 你必须提供一个,或者将你的 Kubernetes 集群与某个云平台集成。

3.4 ExternalName

将服务映射到 externalName 字段的内容(例如,映射到主机名 api.foo.bar.example)。 该映射将集群的 DNS 服务器配置为返回具有该外部主机名值的 CNAME 记录。 集群不会为之创建任何类型代理。

4、无头服务(Headless Services)

service 有一个特别的形态就是 Headless Service。service 创建的时候可以指定 clusterIP:None,告诉 K8s 说我不需要 clusterIP(就是刚才所说的集群里面的一个虚拟 IP),然后 K8s 就不会分配给这个 service 一个虚拟 IP 地址,它没有虚拟 IP 地址怎么做到负载均衡以及统一的访问入口呢?

它是这样来操作的:pod 可以直接通过 service_name 用 DNS 的方式解析到所有后端 pod 的 IP 地址,通过 DNS 的 A 记录的方式会解析到所有后端的 Pod 的地址,由客户端选择一个后端的 IP 地址,这个 A 记录会随着 pod 的生命周期变化,返回的 A 记录列表也发生变化,这样就要求客户端应用要从 A 记录把所有 DNS 返回到 A 记录的列表里面 IP 地址中,客户端自己去选择一个合适的地址去访问 pod。

无头 Service 不会获得集群 IP,kube-proxy 不会处理这类 Service, 而且平台也不会为它们提供负载均衡或路由支持。你可以使用无头 Service 与其他服务发现机制交互,而不必绑定到 Kubernetes 的实现。

5、访问service

启动demo

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: httpd-demo-1
  namespace: test
  labels:
    app: httpd-demo
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    app: httpd-demo

---

apiVersion: v1
kind: Service
metadata:
  name: httpd-demo-2
  namespace: test
  labels:
    app: httpd-demo
spec:
  type: NodePort
  ports:
  - nodePort: 32181
    port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: httpd-demo

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd-demo
  namespace: test
  labels:
    app: httpd-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: httpd-demo
  template:
    metadata:
      labels:
        app: httpd-demo
    spec:
      containers:
      - name: httpd-demo
        image: httpd:latest
ini 复制代码
kubectl --kubeconfig=xxx apply -f service.yaml  

启动一个busybox镜像的pod,方便连接service进行测试

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: busybox-test
  namespace: test
  labels:
    app: busybox
spec:
  containers:
  - name: busybox-test
    image: busybox:latest
    command: ["/bin/sh", "-c"]
    args:
    - |
      sleep 100000

查看当前service

scss 复制代码
kubectl --kubeconfig=xxx get svc -n test

NAME                          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
httpd-demo-1                  ClusterIP   10.30.99.106    <none>        80/TCP         1h
httpd-demo-2                  NodePort    10.30.167.74    <none>        80:32181/TCP   1h

通过nodeIp:nodePort访问 http://xx.xx.xx.xx:32181/

集群内访问 curl 10.30.99.106:80

其他pod访问

bash 复制代码
kubectl --kubeconfig=xxx exec -it -n test busybox-test sh

# 通过clusterIp访问service
wget -O- 10.30.99.106
# 通过环境变量访问service
wget -O- $HTTPD_DEMO_1_SERVICE_HOST
# 通过服务名访问service,如果是不同namespace,加上.namaspace
wget -O- httpd-demo-1
wget -O- httpd-demo-1.test

# 查看环境变量,可以看到写入了很多环境变量,如xxx_SERVICE_HOST xxx_PORT
env |grep HTTPD_DEMO

参考

相关推荐
无言听风雨丶16 小时前
Linux 容器本质探秘:Cgroup 与 Namespace 深度解析与实战
linux·运维·服务器·kubernetes
无言听风雨丶20 小时前
Kubernetes GitOps 持续交付实战:用 Argo CD 让 Git 成为集群事实源
git·elasticsearch·kubernetes
无言听风雨丶1 天前
Kubernetes 控制平面深度剖析:从 kubectl apply 到 etcd 写入的全链路
平面·kubernetes·etcd
openFuyao1 天前
openFuyao x 复旦大学软件工程实验室 Panel 回顾:Agentic时代,集群调度技术体系将如何演进?
kubernetes·openfuyao
螺蛳粉 螺蛳粉1 天前
第 05 篇:etcd 深入:Raft 共识、watch 机制与快照备份恢复实战(底座认知 05)
docker·云原生·容器·kubernetes·etcd·分布式存储·kube-apiserver
相思难忘成疾1 天前
从零搭建 Kubernetes 1.30 集群:kubeadm 部署一主多从实战(RHEL 9.3 + Docker + flannel)
linux·运维·kubernetes
weirong1 天前
给 K8s 加一个自动值班员:分级故障自愈引擎
kubernetes
云和数据.ChenGuang1 天前
Python 闭包详解:从原理到实战
linux·开发语言·人工智能·python·kubernetes
weirong2 天前
为什么 HPA 会震荡?手写一个带冷却窗口的伸缩决策引擎
kubernetes
-星空下无敌2 天前
Windows Docker K8s 安装部署Naocs ,SpringBoot 3.x 4.x 整合Naocs 版本兼容 配置中心、服务注册与发现
windows·docker·nacos·kubernetes·springboot·alibaba