外部访问
一、认识
在 Kubernetes
中,Service
外部访问指的是允许集群外部的用户或系统访问集群内的服务(Pods)
。这种访问方式通常用于将内部服务暴露给外界,如访问 Web
应用、API
服务等。Kubernetes
提供以下几种方式来实现 Service
的外部访问:
-
Ingress
:Ingress
是Kubernetes
的HTTP
和HTTPS
路由入口,使用域名将外部请求转发到内部的Service
。 -
NodePort
: 通过集群节点的某个固定端口(30000-32767
范围内)暴露Service
,外部用户可以通过NodeIP:NodePort
访问。 -
LoadBalancer
: 通过云服务商的负载均衡器(如AWS
ELB
、GCP LB
),直接向外暴露一个外部IP
地址。 -
ExternalName
: 将Kubernetes
内部服务映射到外部DNS
名称,用于访问外部服务。 -
Port Forwarding
: 通过kubectl port-forward
将本地机器的端口映射到Pod
。
二、Ingress
Ingress
: Ingress
是 Kubernetes
的 HTTP
和 HTTPS
路由入口,使用域名将外部请求转发到内部的 Service
。支持路径和主机路由,适合复杂架构。配置稍复杂,需要部署 Ingress Controller
。适合需要基于域名访问服务,支持路径和主机路由规则,适合大型项目或微服务架构。结合 Ingress Controller
(如 Nginx
、Traefik
)替代 NodePort/LoadBalancer
,提供更灵活的路由控制。
2.1 部署 Service
1. 创建两个 Service
和 Deployment
: 用来模拟分别使用两个路径访问不同内容
apiVersion: v1
kind: Service
metadata:
name: web1
labels:
app: web1
spec:
selector:
app: web1
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: web2
labels:
app: web2
spec:
selector:
app: web2
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web1
spec:
replicas: 2
selector:
matchLabels:
app: web1
template:
metadata:
labels:
app: web1
spec:
containers:
- name: web1
image: registry.cn-hangzhou.aliyuncs.com/bolawen/nginx:1.27.1-perl-linux-arm64
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web2
spec:
replicas: 2
selector:
matchLabels:
app: web2
template:
metadata:
labels:
app: web2
spec:
containers:
- name: web2
image: registry.cn-hangzhou.aliyuncs.com/bolawen/nginx:1.27.1-perl-linux-arm64
ports:
- containerPort: 80
2. 应用配置
kubectl apply -f app.yaml
3. 验证服务和 Pod
是否启动成功
kubectl get pods,svc
2.2 安装 Controller
Kubernetes
需要一个 Ingress Controller
来解析和实现 Ingress
规则。常见的 Ingress Controller
:
-
Traefik
-
HAProxy
-
NGINX Ingress Controller
1. 使用 YAML
安装 NGINX Ingress Controller
: 下载 yaml
部署文件
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.5.1/deploy/static/provider/cloud/deploy.yaml
2. 下载并上传所需镜像: 在可科学上网的机器上下载 arm64
镜像,并上传到阿里云个人镜像仓库。
# 1. ingress-nginx/controller
docker pull --platform linux/arm64 registry.k8s.io/ingress-nginx/controller:v1.5.1
docker inspect registry.k8s.io/ingress-nginx/controller:v1.5.1 | grep Architecture
docker tag registry.k8s.io/ingress-nginx/controller:v1.5.1 registry.cn-hangzhou.aliyuncs.com/bolawen/ingress-nginx-controller:v1.5.1-linux-arm64
docker push registry.cn-hangzhou.aliyuncs.com/bolawen/ingress-nginx-controller:v1.5.1-linux-arm64
# 2. ingress-nginx/kube-webhook-certgen
docker pull --platform linux/arm64 registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343
docker inspect registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343 | grep Architecture
docker tag registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343 registry.cn-hangzhou.aliyuncs.com/bolawen/ingress-nginxkube-webhook-certgen:v20220916-gd32f8c343
docker push registry.cn-hangzhou.aliyuncs.com/bolawen/ingress-nginxkube-webhook-certgen:v20220916-gd32f8c343
3. 修改 deploy.yaml
配置文件
# 1. 搜索 images 替换镜像
# 2. 把 LoadBalancer 修改成 NodePort
# 3. 去掉 dnsPolicy: ClusterFirst, 在下面添加
dnsPolicy: ClusterFirstWithHostNet
hostNetwork: true
4. 应用 deploy.yaml
配置文件
# 安装
kubectl apply -f deploy.yaml
# 如需删除
kubectl delete -f deploy.yaml
# 如需强制删除
kubectl delete pod -n ingress-nginx --all --grace-period=0 --force
5. 验证 ingress-nginx
状态
# 1. 检查 ingress-nginx 控制器的 Pods 状态
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx
# 2. 查看 ingress-nginx 控制器的 Pods 日志
kubectl describe pod -n ingress-nginx <PodName>
2.3 编写 Ingress 文件
创建 Ingress
配置 创建 ingress.yaml
文件:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: my-app.local
http:
paths:
- path: /web1
pathType: Prefix
backend:
service:
name: web1
port:
number: 80
- path: /web2
pathType: Prefix
backend:
service:
name: web2
port:
number: 80
2.4 部署 Ingress 服务
kubectl apply -f ingress.yaml
2.5 验证 Ingress 服务
kubectl get ingress
2.6 测试 Ingress 服务
1. 编辑 /etc/hosts
: 添加以下条目,将 my-app.local
指向集群的外部 IP
地址:
<CLUSTER-EXTERNAL-IP> my-app.local
2. 访问如下路径测试
http://my-app.local/web1
http://my-app.local/web2
三、NodePort
NodePort
: 通过集群节点的某个固定端口(30000-32767
范围内)暴露 Service
,外部用户可以通过 NodeIP:NodePort
访问。简单易用,配置轻量级。每个服务占用一个端口,安全性较低。适合简单的测试环境或小型集群。
3.1 访问
1. 创建 Service
: 注意: 注意,环境变量仅在 Pod
启动时注入。因此,必须先创建 Service
, 然后创建 Deployment
.
apiVersion: v1
kind: Service
metadata:
name: test-service
labels:
app: test-nginx
spec:
selector:
app: test-nginx
type: NodePort
ports:
- port: 80
name: nginx-server
protocol: TCP
targetPort: 80
nodePort: 30001
kubectl apply -f test-service.yaml
2. 创建 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
labels:
app: test-nginx
spec:
replicas: 3
selector:
matchLabels:
app: test-nginx
template:
metadata:
labels:
app: test-nginx
spec:
containers:
- name: test-nginx
image: registry.cn-hangzhou.aliyuncs.com/bolawen/nginx:1.27.1-perl-linux-arm64
ports:
- containerPort: 80
kubectl apply -f test-deployment.yaml
3. 查看 Node IP
kubectl get node // 查看 Node 节点 Name
kubectl describe node [Node Name] // 查看 Node 节点信息, 找到 InternalIP 就是当前 Node 节点的 IP 地址
4. 基于 Node IP
外部访问
http://<NodeIP>:30001
四、LoadBalancer
LoadBalancer
: 通过云服务商的负载均衡器(如 AWS
ELB
、GCP LB
),直接向外暴露一个外部 IP
地址。自动化配置云负载均衡,易于使用。依赖云提供商,可能产生额外成本。适合运行在云环境中,需要自动化负载均衡器配置。
4.1 访问
1. 创建 Service
: 注意: 注意,环境变量仅在 Pod
启动时注入。因此,必须先创建 Service
, 然后创建 Deployment
.
apiVersion: v1
kind: Service
metadata:
name: test-service
spec:
selector:
app: test-nginx
type: LoadBalancer
ports:
- port: 80 # Service 内部端口
targetPort: 8080 # Pod 暴露的端口
kubectl apply -f test-service.yaml
2. 创建 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
spec:
replicas: 3
selector:
matchLabels:
app: test-nginx
template:
metadata:
labels:
app: test-nginx
spec:
containers:
- name: test-nginx
image: registry.cn-hangzhou.aliyuncs.com/bolawen/nginx:1.27.1-perl-linux-arm64
ports:
- containerPort: 80
kubectl apply -f test-deployment.yaml
3. 外部访问: 部署后,Kubernetes
会创建一个云负载均衡器,并分配一个外部 IP
地址。
http://<External-IP>
五、ExternalName
ExternalName
: 将 Kubernetes
内部服务映射到外部 DNS
名称,用于访问外部服务。集群内外部服务映射,配置简单。仅支持 DNS
名称,功能有限。适合集群内部需要通过 Service
访问外部资源。
5.1 访问
1. 创建 Service
: 注意: 注意,环境变量仅在 Pod
启动时注入。因此,必须先创建 Service
, 然后创建 Deployment
.
apiVersion: v1
kind: Service
metadata:
name: test-service
spec:
selector:
app: test-nginx
type: ExternalName
externalName: api.external.com
kubectl apply -f test-service.yaml
2. 创建 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
spec:
replicas: 3
selector:
matchLabels:
app: test-nginx
template:
metadata:
labels:
app: test-nginx
spec:
containers:
- name: test-nginx
image: registry.cn-hangzhou.aliyuncs.com/bolawen/nginx:1.27.1-perl-linux-arm64
ports:
- containerPort: 80
kubectl apply -f test-deployment.yaml
3. 外部访问: 内部 Pods
通过 external-service
访问 api.external.com
。
六、Port Forwarding
Port Forwarding
: 通过 kubectl port-forward
将本地机器的端口映射到 Pod
。简单临时调试方式,无需额外配置。仅用于临时调试,性能和稳定性不足。适合调试、测试时临时访问。
6.1 访问
1. 转发
kubectl port-forward svc/my-service 8080:80
2. 访问
http://localhost:8080