K8s 基础:Pod 与服务暴露
K8s 基础:Pod 与服务暴露
两块基础概念:Pod 是什么、怎么管;以及集群内的服务怎么暴露给集群外访问。
Pod
Pod 是 Kubernetes 里最小的部署单元。一个 Pod 包含一个或多个相对紧密耦合的容器,这些容器共同调度、跑在同一节点上,共享上下文、网络命名空间和卷。
在非云环境里,跑在同一物理机/虚拟机上的应用,类比成跑在同一个逻辑主机上的云应用——Pod 就是这个 "逻辑主机"。
Pod 被设计成短暂的、一次性的实体。它不会自愈:某个 Pod 因为缺资源被控制器终止后,不会自己恢复,而是由控制器按目标状态重新创建。所以一般很少直接创建单独的 Pod(即使是单例),而是用 workload 资源去管。
注意:重启 Pod 里的容器,和重启 Pod 是两回事。Pod 本身是运行容器的环境,不是一个进程,它会一直存在直到被删除。给 Pod 起名时,名字要是合法的 DNS 子域名。
直接创建 Pod 的方式(不推荐常用):
kubectl run nginx --image=nginx
kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml
管理多个 Pod 的 workload 资源:
- Deployment — 无状态应用,管副本和滚动更新
- StatefulSet — 有状态应用,Pod 有稳定的标识和存储
- DaemonSet — 每个节点跑一个 Pod
控制器会处理副本、发布和自愈。比如某个节点挂了,控制器发现该节点上的 Pod 停了,就创建替代 Pod,调度器把它放到健康节点上。
服务暴露
Service 默认 type 是 ClusterIP,只在集群内部可访问。要让集群外能访问,有三种方式。
| 方式 | 原理 | 缺点 |
|---|---|---|
| NodePort | 每个节点开一个静态端口,宿主机端口映射到 Pod 端口 | 服务多了对外暴露的端口就多,不安全也不好维护 |
| LoadBalancer | Service 绑负载均衡器,给一个公网 IP | 每个 Service 都要一个 LB,且 LB 由云厂商提供,要花钱 |
| Ingress | 一个 controller 按 ingress 规则转发 | 需要先装控制器 |
NodePort
type 改成 NodePort,不指定 nodePort 就自动分配,通过 节点IP:nodePort 访问:
apiVersion: v1
kind: Service
metadata:
name: test
namespace: elk
spec:
ports:
- name: web
nodePort: 32393 # 指定 nodePort
port: 5200
protocol: TCP
targetPort: 5200
type: NodePort
LoadBalancer
type 改成 LoadBalancer,绑定已在云上创建的负载均衡器,通过 "LB 域名:端口" 访问。以腾讯云为例,用 annotations 指定 LB ID:
apiVersion: v1
kind: Service
metadata:
annotations:
service.kubernetes.io/tke-existed-lbid: <lb-id> # 指定负载均衡器 ID
name: external-auth
spec:
externalTrafficPolicy: Local
ports:
- name: base
port: 7800
protocol: TCP
targetPort: 7800
selector:
app: auth
type: LoadBalancer
Ingress
先装 ingress 控制器(K8s 官方维护 AWS、GCE、Nginx 三种),以 Nginx Ingress 为例。必须有控制器,ingress 规则才生效。
注意 IngressNginxController 的端口映射:80 转发到某个节点端口(如 30692),443 转发到另一个(如 32495),这些端口是变化的,具体看控制器说明。
按域名分流:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-elk
namespace: elk
spec:
ingressClassName: ingress-ctr
rules:
- host: kibana.example.com # 精确匹配或通配 *.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: elk
port:
number: 5601
- host: elastic.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: elk
port:
number: 9200
按路径分流(路径要 Pod 支持才行)。pathType 有三种:
- Exact:精确匹配 URL 路径,区分大小写
- Prefix:按
/分隔的前缀匹配,区分大小写 - ImplementationSpecific:匹配方法取决于 IngressClass
spec:
rules:
- host: "foo.bar.com"
http:
paths:
- pathType: Prefix
path: "/bar"
backend:
service:
name: service1
port:
number: 80
- pathType: Prefix
path: "/foo"
backend:
service:
name: service2
port:
number: 80
默认后端:没有 host/path 匹配时流量路由到 defaultBackend。如果没设任何 rules,就必须指定 defaultBackend:
spec:
defaultBackend:
service:
name: auth
port:
number: 7800