11.1 LoadBalancer Service 简介
之前介绍了 NodePort Service,我们知道了通过任意一个 NodeIP:NodePort 就可以访问集群服务,假如集群有多个 Node 节点,比如 10 个、20 个,如何分配对于这些节点的访问请求呢?这个时候最好是有一个负载均衡器,外部的客户端请求只需要访问负载均衡器的 IP 地址,然后由外部负载均衡器分配转发流量到后端 Node 的 NodePort 上,具体如下图所示:

LoadBalancer Service 实例
LoadBalancer 组件一般是独立于 Kubernetes 集群之外的,大部分的时候是一个硬件的负载均衡器,也可以用软件方式实现,比如:HAProxy 或是 Nginx。对于每个服务都需要配置一个与之对应的 LoadBalancer 实例,这样会增加工作量和出错的概率。
使用 nginx 软件手动实现负载均衡
新建 tomcat-deployment.yaml,并向其中写入如下内容:
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat
spec:
selector:
matchLabels:
app: tomcat
replicas: 2
template:
metadata:
labels:
app: tomcat
spec:
containers:
- name: tomcat
image: kubeguide/tomcat-app:v1
ports:
- containerPort: 8080
执行创建:
$ kubectl create -f tomcat-deployment.yaml
deployment.apps/tomcat created
新建 tomcat-svc.yaml 文件,并向其中写入如下内容:
apiVersion: v1
kind: Service
metadata:
name: tomcat-svc
spec:
type: NodePort
ports:
- port: 80 # 设置 ClusterIP 对应的端口为 80
targetPort: 8080 # Pod 开放的端口为 8080
nodePort: 30001 # 设置在 Node 上开放的端口为 30001
selector:
app: tomcat
执行创建:
$ kubectl create -f tomcat-svc.yaml
service/tomcat-svc created
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
tomcat-svc NodePort 10.96.112.206 <none> 80:30001/TCP 21s
$ curl 192.168.0.31:30001
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Apache Tomcat/8.0.35</title>
<link href="favicon.ico" rel="icon" type="image/x-icon" />
<link href="favicon.ico" rel="shortcut icon" type="image/x-icon" />
<link href="tomcat.css" rel="stylesheet" type="text/css" />
</head>
...
接下来安装并配置 nginx 作为负载均衡器进行模拟。
# 准备环境中已经安装 nginx,查看版本信息:
$ nginx -v
nginx version: nginx/1.19.0
# 向nginx配置文件中添加内容:
$ cat >/etc/nginx/nginx.conf<<EOF
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
# 添加 k8s 集群所有可用的 nodeIP:nodePort
upstream k8snode {
server 192.168.0.31:30001;
server 192.168.0.32:30001;
server 192.168.0.33:30001;
}
# 设置虚拟主机
server {
# 监听 80 端口
listen 80;
location / {
# 反向代理指令,将所有的请求都发送给 k8snode 机器组中的机器
proxy_pass http://k8snode;
}
}
}
EOF
# 检查配置文件是否正确并使之生效
$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ nginx -s reload
直接通过浏览器访问地址 http://localhost:80:

11.2 ExternalName Service 简介
ExternalName Service 是一种特殊类型的 Service,主要用于访问位于集群外部的服务。它没有选择器 Selector,也没有定义任何端口 Port 或是 Endpoints。它的作用是返回集群外服务的域名。
通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段对应的内容(比如:api.github.com)。使用这种类型的服务不会创建任何类型的代理。
新建 externalname-svc.yaml 文件,并向其中写入如下内容:
apiVersion: v1
kind: Service
metadata:
name: en-svc
namespace: default
spec:
type: ExternalName # type 类型需要选择 ExternalName
externalName: api.github.com # externalName 中填写外部服务对应的域名
执行创建:
$ kubectl create -f externalname-svc.yaml
service/en-svc created
# 查看服务,可以看到 en-svc 服务没有集群 IP,只有一个 EXTERNAL-IP,为:api.github.com
$ kubectl get svc en-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
en-svc ExternalName <none> api.github.com <none> 23s
先查看api.github.com对应的IP:
$ ping api.github.com
PING api.github.com (13.250.168.23) 56(84) bytes of data.
集群内部通过 DNS 查找 en-svc 服务对应的 IP 地址,这里单独运行一个使用 utils 镜像创建的 pod 执行命令(镜像中已经安装了 dnsutils):
$ kubectl run --generator=run-pod/v1 --rm utils -it --image tutum/dnsutils bash
If you don't see a command prompt, try pressing enter.
root@utils:/# nslookup en-svc
Server: 10.96.0.10
Address: 10.96.0.10#53
en-svc.user-test.svc.cluster.local canonical name = api.github.com.
Name: api.github.com
Address: 13.250.168.23
使用 ExternalName Service 可以使集群连接外部服务,在 spec.externalName 字段中定义外部服务的域名即可使用。
评论区