K8S从入门到实战(1)
pod概念和k8s网络
基于docker模拟pod
pause容器作为基础容器,创建一个共享的网络、IPC、PID 命名空间。- 这样三个容器就像 Kubernetes 的一个 Pod 一样,共享同一个 IP、网络栈、进程空间,互相之间可以直接通信。
# 1. 启动 pause 容器docker run --name pause -p 8080:80 -d registry.aliyuncs.com/google_containers/pause:3.1
# 2. 启动 nginx 容器,共享 pause 的网络/IPC/PID 命名空间docker run --name nginx -v `pwd`/nginx.conf:/etc/nginx/nginx.conf --net=container:pause --ipc=container:pause --pid=container:pause -d nginx
# 3. 启动 ghost 容器,同样共享 pause 的命名空间docker run -d --name ghost --net=container:pause --ipc=container:pause --pid=container:pause ghost当你部署了kubernetes时,你就拥有了一个集群。
- 一个 Kubernetes 集群包含两种类型的资源: Master 调度整个集群,负责管理整个集群。 Master协调集群中的所有活动,例如调度应用、维护应用的所需状态、应用扩容以及推出新的更新。Node是一个虚拟机或者物理机,它在 Kubernetes 集群中充当工作机器的角色每个Node都有Kubelet, 它管理 Node 而且是 Node 与 Master 通信的代理。 Node 还应该具有用于处理容器操作的工具,例如 Docker 或 rkt 。处理生产级流量的 Kubernetes 集群至少应具有三个 Node
- 工作节点(worker nodes )上运行着 pods,控制平台(controller plane)负责管理集群中的 nodes 和 pods。在生产环境中,控制平台通常在多台计算机上运行,而集群通常也运行在多个 nodes 上,从而提供了很强的容错能力和高可用性。
- kubernetes集群所需的组件。分为控制平台组件(Control Plane Components)也叫 master 组件(master Components ) 和 节点组件(Node Components)

控制平台组件(master 组件)
- 控制平台中的组件对集群进行全局决策(比如:调度),并且监控和应对集群事件(比如:当 deployment 中的 replicas 字段发生变化时,创建/删除 pod)。
- 控制平台组件可以运行在集群中的任何一台机器上,但是为了简单,通常会在同一台物理机上部署所有的控制平台组件,同时要求用户的容器不能部署在控制平台组件所在的物理机上。
# kube-apiserver
- API server 是 kubernetes 平台组件之一,它将 kubernetes API 暴露给用户,用户就是通过和 kube-apiserver 交互实现控制集群的。在一个集群中可以部署多个 kube-apiserver,并在他们之间执行“负载均衡”。
# etcd
- 集群的所有数据都存储在 etcd 中,如果你选用 etcd 作为 kubernetes 的后端存储,请不要忘记对这些存储的数据做备份(back up)。 etcd 的更深入的信息可以参看官方文档:documentation
# kube-scheduler
- 控制平台组件监控新创建但还没有为其分配 node 的 pod,之后选择一个适合的 node为 pod 分配,这就是 调度器(scheduler)负责干的事情。
- 在做调度决策是所考虑的因素有:individual and collective resource requirements, hardware/software/policy constraints, affinity and anti-affinity specifications, data locality, inter-workload interference, and deadlines。
# kube-controller-manager
- 控制平台组件中运行着许多控制器进程(controller processes)。理论上来说,每一个控制器都是一个独立的进程,但为了降低复杂性,将所有的控制器进程都编译到同一个二进制文件中并且运行在用一个进程中。
# 节点组件(Node Components)
- 节点组件在集群中的每个节点上都有运行,维护运行中的 pod,并提供 kubernetes 运行时环境。
# kubelet
- 集群中的每个 node 上都运行着一个代理(agent),它确保 pod 中的 container 是正在运行的。
- kubelet 读取一组 pod说明书(PodSpec),并确保 PodSpec中描述的 container 正在运行且运行状况良好。kubelet 只能管理 Kubernetes 创建的 container。
# kube-proxy
- kube-proxy 是个网络代理,集群中的每个 node 上都运行着它。kube-proxy 维护节点上的网络规则,这些网络规则允许集群内部或外部的网络会话与 pod 进行网络通信。
# Container runtime
- 这个组件是个软件,它负责跑 container,Kubernetes 支持的 container runtimes 有:Docker,containerd-CRI-O,和任何 Kubernetes CRI 的实现。
# 插件 (Addons)
- 插件(也被叫做附加组件)使用 Kubernetes 资源(比如:DamonSet、Deployment)来实现集群功能(当恰当的附加组件出现时,kubernetes 集群才能提供正常的集群功能)。因为这些插件提供集群功能,所以这些插件都在 kube-system命名空间中。Kubernetes中可以使用的插件。
# 总结
Kubernetes 集群的组件分为两部分:master 组件和 node 组件。
- master 组件包括:kube-apiserver、etcd、kube-scheduler、kube-controller-manager。
- node 组件包括:kubelet、kube-proxy、container-runtime。
Kubernetes主要由以下几个核心组件组成:
- etcd保存了整个集群的状态;
- apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;
- controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
- scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;
- kubelet负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;
- Container runtime负责镜像管理以及Pod和容器的真正运行(CRI);
- kube-proxy负责为Service提供cluster内部的服务发现和负载均衡;
网络模型原则
- 在不使用网络地址转换(NAT)的情况下,集群中的Pod能够与其他任意Pod进行通信
- 在不使用网络地址转换(NAT)的情况下,集群节点运行的程序能与同一节点上的任何Pod进行通信
- 每个Pod都能有自己的IP地址,并且任意其他Pod都可以通过相同的这个地址进行访问
CNI都是可执行文件,我们只需要使用json定义我们想干什么就行了

Main 插件,创建具体网络设备(bridge: 网桥设备,连接 container 和 host;ipvlan: 为容器增加 ipvlan 网卡;loopback: IO 设备;macvlan: 为容器创建一个 MAC 地址;ptp: 创建一对 Veth Pair;vlan: 分配一个 vlan 设备;host-device: 将已存在的设备移入容器内)
IPAM 插件:负责分配 IP 地址(dhcp: 容器向 DHCP 服务器发起请求,给 Pod 发放或回收 IP 地址;host-local: 使用预先配置的 IP 地址段来进行分配;static: 为容器分配一个静态 IPv4/IPv6 地址,主要用于 debug)
META 插件:其他功能的插件(tuning: 通过 sysctl 调整网络设备参数;portmap: 通过 iptables 配置端口映射;bandwidth: 使用 Token Bucket Filter 来限流;sbr: 为网卡设置 source based routing;firewall: 通过 iptables 给容器网络的进出流量进行限制)
Windows 插件:专门用于 Windows 平台的 CNI 插件(win-bridge 与 win-overlay 网络插件)
第三方网络插件:第三方开源的网络插件众多,每个组件都有各自的优点及适应的场景,难以形成统一的标准组件,常用有 Flannel、Calico、Cilium、OVN 网络插件
calica-架构-VXLAN-1
什么是 VXLAN?
- VXLAN,即 Virtual Extensible LAN(虚拟可扩展局域网),是 Linux 本身支持的一种网络虚拟化技术。VXLAN 可以完全在内核态实现封装和解封装工作,从而通过 “隧道” 机制,构建出覆盖网络(Overlay Network)
- 基于三层的 “二层” 通信,层即 vxlan 包封装在 udp 数据包中,要求 udp 在 k8s 节点间三层可达;二层即 vxlan 封包的源 mac 地址和目的 mac 地址是自己的 vxlan 设备 mac 和对端 vxlan 设备 mac 实现通讯。
IPIP
➤ Linux 原生内核支持
➤ IPIP 隧道的工作原理是将源主机的 IP 数据包封装在一个新的 IP 数据包中,新的 IP 数据包的目的地址是隧道的另一端。在隧道的另一端,接收方将解封装原始 IP 数据包,并将其传递到目标主机。IPIP 隧道可以在不同的网络之间建立连接,例如在 IPv4 网络和 IPv6 网络之间建立连接。
k8s安装
软路由配置
下载ikuai
建议选择32位的。因为虚拟机要求的硬件低,只需要,一核一G。生成环境还是64位的好

虚拟机配置
虚拟机都选择其他,硬件要求看上图。网卡选择主机模式。剩下的磁盘什么的都默认。
退出,给他再加上一个可以连外网的网卡nat模式,就是后面的wan口
进入ikuai配置
(1)先配置LAN口,192.168.66.200/255.255.255.0,这个是vm里面设置好的虚拟网卡,在66网段,我的Nat虚拟网卡是44网段的。后面会看到

(2)主机输入192.168.66.200 进如ikuai的web管理界面

进入设置wan口,使得这个可以上网。自动获取就行了(DHCP)
这里就看见我设置的vm里面设置的虚拟网卡了,44网段的,就是通过这个Nat在通过主机转发上网的

给三个虚拟机都设置网关
也就是刚进来给ikuai设置的LAN口,三个虚拟机和ikuai可以相互通信,上网就通过ikuai的WAN口

给所有虚拟机里面第二个Nat网卡设置开机不自启
[root@k8s-master01 ~]# vi /etc/NetworkManager/system-connections/ens192.nmconnection
现在就全部靠路由上网了
ens192 网卡就没有启动
[root@k8s-master01 ~]# ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:0c:29:31:d5:3e brd ff:ff:ff:ff:ff:ff altname enp3s0 inet 192.168.66.11/24 brd 192.168.66.255 scope global noprefixroute ens160 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe31:d53e/64 scope link noprefixroute valid_lft forever preferred_lft forever3: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:0c:29:31:d5:48 brd ff:ff:ff:ff:ff:ff altname enp11s04: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 86:bc:9b:71:e4:a2 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever
准备
换主机名,方便后面操作
(1)hostnamectl set-hostname k8s-master01
(2)hostnamectl set-hostname k8s-node01
(3)hostnamectl set-hostname k8s-node02
主机名ip映射
- vi /etc/hosts # 添加到末尾, m1 是缩写
192.168.66.11 k8s-master01 m1192.168.66.12 k8s-node01 n1192.168.66.13 k8s-node02 n2安装cri-docker
# 安装 cri-dockerwget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.9/cri-dockerd-0.3.9.amd64.tgztar -xf cri-dockerd-0.3.9.amd64.tgzcp cri-dockerd/cri-dockerd /usr/bin/chmod +x /usr/bin/cri-dockerd
# 配置cri-docker服务 加入到systemctl中cat <<"EOF" > /usr/lib/systemd/system/cri-docker.service[Unit]Description=CRI Interface for Docker Application Container EngineDocumentation=https://docs.mirantis.comAfter=network-online.target firewalld.service docker.serviceWants=network-online.targetRequires=cri-docker.socket
[Service]Type=notifyExecStart=/usr/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.8ExecReload=/bin/kill -s HUP $MAINPIDTimeoutSec=0RestartSec=2Restart=alwaysStartLimitBurst=3StartLimitInterval=60sLimitNOFILE=infinityLimitNPROC=infinityLimitCORE=infinityTasksMax=infinityDelegate=yesKillMode=process
[Install]WantedBy=multi-user.targetEOF
# 添加 cri-docker 套接字cat <<"EOF" > /usr/lib/systemd/system/cri-docker.socket[Unit]Description=CRI Docker Socket for the APIPartOf=cri-docker.service
[Socket]ListenStream=%t/cri-dockerd.sockSocketMode=0660SocketUser=rootSocketGroup=docker
[Install]WantedBy=sockets.targetEOF
# 启动 cri-docker 对应服务systemctl daemon-reloadsystemctl enable cri-dockersystemctl start cri-dockersystemctl is-active cri-docker安装
开始安装 kubelet kubectl kubeadm,初始化master节点
# 添加 kubeadm yum 源cat <<EOF > /etc/yum.repos.d/kubernetes.repo[kubernetes]name=Kubernetesbaseurl=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/enabled=1gpgcheck=1gpgkey=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/repodata/repomd.xml.keyexclude=kubelet kubeadm kubectl cri-tools kubernetes-cniEOF
# 安装 kubeadm 1.29 版本yum install -y kubelet-1.29.0 kubectl-1.29.0 kubeadm-1.29.0 --disableexcludes=kubernetessystemctl enable kubelet.service# 初始化主节点kubeadm init \ --apiserver-advertise-address=192.168.66.11 \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version 1.29.2 \ --service-cidr=10.10.0.0/12 \ --pod-network-cidr=10.244.0.0/16 \ --ignore-preflight-errors=all \ --cri-socket unix:///var/run/cri-dockerd.sock# 创建配置文件mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config
# 其他节点 加入到主节点 如果是docker就必须加上最后的参数 --cri-socket unixkubeadm join 192.168.66.11:6443 --token xpr121.elrcxawcf9ouext9 \ --discovery-token-ca-cert-hash sha256:e5547eb91684b068ee77d7f3f474a251a4c405f8723ce2ca723abfa3d6eef7d5 \ --cri-socket unix:///var/run/cri-dockerd.sock# work token 过期后,重新申请kubeadm token create --print-join-command
# worker 加入kubeadm join 192.168.66.11:6443 --token a6xh07.yg9wh2vru2gr1uwb \ --discovery-token-ca-cert-hash sha256:7cd8499abae48c8403800152cc0f655ac704ea00ae30a549acd9bbac7b26dca4 \ --cri-socket unix:///var/run/cri-dockerd.sock初始化失败重新来
# 重置 kubeadmkubeadm reset -f --cri-socket unix:///var/run/cri-dockerd.sock
# 清理残留目录(这些残留常会导致证书或配置错误)rm -rf /etc/kubernetes/rm -rf /var/lib/etcd/rm -rf /var/lib/kubelet/rm -rf $HOME/.kube/rm -rf /etc/cni/net.d/安装网络插件
# Calico 官方文档地址:# https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises#install-calico-with-kubernetes-api-datastore-more-than-50-nodes
# 下载 Calico 清单文件curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.3/manifests/calico-typha.yaml -o calico.yaml
# 关键点:修改 CALICO_IPV4POOL_CIDR 为你集群的 Pod 网段# 修改为 BGP 模式:关闭 IPIP 隧道# 找到配置项:- name: CALICO_IPV4POOL_IPIP value: "Always" # 改成 "Off"# 依次拉取 4 个核心镜像docker pull calico/cni:v3.26.3docker pull calico/node:v3.26.3docker pull calico/kube-controllers:v3.26.3docker pull calico/typha:v3.26.3
# 在 Master 节点上执行:kubectl apply -f calico.yamlk8s资源清单
什么是资源
概念
k8s中所有的内容都抽象为资源,资源实例化之后,叫做对象
分类

资源清单的编写
结构

如何查看 接口组/版本
[root@k8s-master01 ~]# kubectl explain podKIND: PodVERSION: v1
DESCRIPTION: Pod is a collection of containers that can run on a host. This resource is created by clients and scheduled onto hosts.
[root@k8s-master01 ~]# kubectl explain deploymentGROUP: appsKIND: DeploymentVERSION: v1
DESCRIPTION: Deployment enables declarative updates for Pods and ReplicaSets.所以 第一个pod的是 v1
第一个是 apps/v1
demo
apiVersion: v1kind: Podmetadata: name: pod-demo namespace: default labels: app: myappspec: containers: - name: myapp-1 # 换成这个版本的 Nginx,格式更新,兼容性好 image: registry.aliyuncs.com/google_containers/nginx-slim:0.20 - name: busybox-1 # 保持这个,因为你刚才已经拉取成功了 image: registry.aliyuncs.com/google_containers/busybox:1.27 command: - "/bin/sh" - "-c" - "sleep 3600"pod的生命周期
initC
init 容器与普通的容器非常像,除了如下两点:
-
init 容器总是运行到成功完成为止
-
每个 init 容器都必须在下一个 init 容器启动之前成功完成,所以init容器是线性启动的
如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止。
然而,如果 Pod 对应的 restartPolicy 为 Never,它不会重新启动
探针
三种探测方式 exec、tcp、http
探针是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的 Handler。有三种类型的处理程序:
➤ ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功
➤ TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的
➤ HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的
每次探测都将获得以下三种结果之一:
➤ 成功:容器通过了诊断。
➤ 失败:容器未通过诊断。
➤ 未知:诊断失败,因此不会采取任何行动
readinessProbe 就绪探针
如果没有添加就绪探针,默认就是就绪的。添加后,所有容器都通过才标记pod是就绪的
介绍:k8s 通过添加就绪探针,解决尤其是在扩容时保证提供给用户的服务都是可用的。
➤ initialDelaySeconds:容器启动后要等待多少秒后探针开始工作,单位 “秒”,默认是 0 秒,最小值是 0
➤ periodSeconds:执行探测的时间间隔(单位是秒),默认为 10s,单位 “秒”,最小值是 1
➤ timeoutSeconds:探针执行检测请求后,等待响应的超时时间,默认为 1s,单位 “秒”,最小值是 1
➤ successThreshold:探针检测失败后认为成功的最小连续成功次数,默认值为 1。必须为 1 才能激活和启动,最小值为 1
➤ failureThreshold:探测失败的重试次数,重试一定次数后将认为失败,默认值为 3,最小值为 1
livenessProbe 存活探针
介绍:k8s 通过添加就绪探针,解决容器虽然活着但是已经死了的问题。运行但是无法提供服务的问题
参数与上面的相同
startupProbe 启动探针
介绍:k8s 在 1.16 版本后增加 startupProbe 探针,主要解决在复杂的程序中 readinessProbe、livenessProbe 探针无法更好的判断程序是否启动、是否存活。
服务于上面两个探针,防止他们一上来就探测杀死容器,无限循环
hook 钩子
Pod hook(钩子)是由 Kubernetes 管理的 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。可以同时为 Pod 中的所有容器都配置 hook。
Hook 的类型包括两种:
- exec:执行一段命令
- HTTP:发送 HTTP 请求
pod控制器
ReplicationController 和 ReplicaSet
-
核心作用:保证集群中指定数量的 Pod 副本始终处于运行状态,Pod 异常时自动重建补足
-
区别:ReplicationController 是旧版 API 已废弃,ReplicaSet 是新版实现,支持更强大的标签选择器
-
注意:日常几乎不直接创建 ReplicaSet,由 Deployment 自动管理
apiVersion: v1kind: ReplicationControllermetadata:name: rc-demospec:replicas: 3selector:app: rc-demotemplate:metadata:labels:app: rc-demospec:containers:- name: rc-demo-containerimage: nginx:alpineenv:- name: GET_HOSTS_FROMvalue: dns- name: zhangsanvalue: "123"img RC 控制器
保障当前的 Pod 数量与期望值一致
RS 控制器
功能与 RC 控制器类似,但是多了标签选择的运算方式
rs 在标签选择器上,除了可以定义键值对的选择形式,还支持
matchExpressions字段,可以提供多种选择。目前支持的操作包括:
- In:label 的值在某个列表中
- NotIn:label 的值不在某个列表中
- Exists:某个 label 存在
- DoesNotExist:某个 label 不存在
Deployment
- 核心作用:Kubernetes 最常用的无状态应用部署控制器,提供完整的声明式应用生命周期管理
- 核心能力:滚动更新、版本回滚、扩缩容、灰度发布
- 适用场景:Web 服务、API 服务、微服务等所有无状态应用
kubectl create、apply、replace
create
创建资源对象
-
-f
通过基于文件的创建,但是如果此文件描述的对象存在,那么哪怕文件描述的信息发生了改变,再次提交时也不会应用
apply
创建资源对象、修改资源对象
-
-f
基于文件创建,如果目标对象与文件本身发生改变,那么会根据文件的指定一一修改目标对象的属性(部分更新)
replace
创建资源对象、修改资源对象
-
-f
基于文件创建,如果目标对象与文件本身发生改变,那么会重建此对象(替换)
Deployment - 常用命令
$ kubectl create -f deployment.yaml —record
—record 参数可以记录命令,我们可以很方便的查看每次 revision 的变化
$ kubectl scale deployment nginx-deployment —replicas 10
为
nginx-deployment配置水平自动扩缩容,最小副本数 10、最大副本数 15,当 Pod CPU 使用率超过 80% 时自动扩容。
$ kubectl autoscale deployment nginx-deployment —min=10 —max=15 —cpu-percent=80
在线更新 Deployment 中容器的镜像版本,会自动触发滚动更新,不中断服务。
$ kubectl set image deployment/nginx-deployment nginx-deployment-container=wangyanglinux/myapp
$ kubectl rollout undo deployment/nginx-deployment
# 可以直接创建一个资源清单模版文件来,--dry-run 白干kubectl create deployment myapp --image=nginx:latest --dry-run -o yaml > deployment.yaml.tmpDaemonSet
- 核心作用:确保集群中每一个(或指定的)节点上都运行一个相同的 Pod 副本
- 适用场景:节点级组件部署,如日志采集、监控代理、网络插件等
DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
Job/CronJob
- Job:一次性任务控制器,保证 Pod 成功执行一次后自动退出,适合一次性计算、批量处理
- CronJob:定时任务控制器,基于 Cron 表达式周期性执行 Job,适合定时备份、定时报表等场景
service
service 概念原理
Service 就是 Pod 组的「固定访问入口 + 负载均衡器」
- 它通过
Label Selector(标签选择器),把一堆提供相同服务的 Pod 归为一组 - 给这组 Pod 一个永远不变的固定地址,不用管 Pod 怎么重启、IP 怎么变
- 访问请求发给这个固定地址,Service 会自动转发给组内健康的 Pod,还能自动分摊流量
service工作原理及使用
cluserIP
公司内部的内线电话
- 只有公司内部员工(集群内 Pod / 节点)能打,外面的人(集群外)打不通
- 号码固定不变,哪怕员工(Pod)调岗、换工位,内线号码永远不变
- 打内线时,会自动帮你转接到对应的员工,不用记每个人的分机号

nodePort
NodePort: 在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过 <NodeIP>:NodePort 来访问该服务
apiVersion: v1kind: Servicemetadata: name: nginx-nodeport-svcspec: # 指定模式为 NodePort type: NodePort ports: # Service 内部端口 - port: 80 # 后端 Pod 的端口 targetPort: 80 # 可选:手动指定 NodePort 端口,不写则自动分配 nodePort: 30080 # 标签选择器,匹配后端 Pod selector: app: nginx

Endpoints
Endpoints(全称 Endpoints API Resource)是 Kubernetes 集群中连接 Service 和后端实际服务的核心桥梁,是整个 K8s 服务发现、流量转发体系的底层核心。
有标签选择器的 Service(自动模式)
这是最常用的标准用法,也是 Kubernetes 原生的自动服务发现模式。
核心规则
- 当你创建一个定义了
spec.selector标签选择器的 Service 时,Kubernetes 会自动创建一个同名的 Endpoints 资源对象,完全无需人工干预。 - Endpoints 资源的匹配逻辑严格遵循以下规则:
- 匹配范围:和 Service 在同一个 Namespace 内的 Pod(跨 Namespace 的 Pod 无法被自动匹配)
- 匹配条件:Pod 的标签是 Service 标签选择器的子集(即 Pod 必须包含 Service 选择器里的所有标签,多出来的标签不影响匹配)
- 健康检查:仅匹配处于「就绪(Ready)」状态的 Pod(未就绪、正在启动、异常退出的 Pod 不会被加入 Endpoints)
- 自动维护:当符合条件的 Pod 发生创建、销毁、标签变更、就绪状态变化时,Kubernetes 会实时自动更新 Endpoints 列表,确保流量只会转发到健康的后端 Pod。
无标签选择器的 Service(手动模式)
这是用于「自定义后端」的高级用法,适合后端不在 Kubernetes 集群内、或需要手动控制流量目标的场景。
核心规则
- 当你创建没有定义
spec.selector字段的 Service 时,Kubernetes 不会自动创建同名的 Endpoints 资源,完全需要集群管理员手动创建和维护 Endpoints 对象。 - 匹配逻辑:Endpoints 里的后端地址,完全由管理员手动填写,支持:
- 集群外部的物理机、云服务器地址
- 其他 Namespace 内的 Pod 地址
- 异构系统的服务端点(比如数据库、中间件、外部 API 等)
- 流量转发:Service 会把收到的流量,直接转发到你手动在 Endpoints 里填写的所有端点,不会自动检查后端状态,需要你自己维护端点的健康。
配置内部流量策略
配置内部流量策略,二选一
internalTrafficPolicy: Local # 仅转发到同节点Pod
internalTrafficPolicy: Cluster # 转发到集群所有Pod(默认)
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!