跳到主要内容

外部访问

2024年11月20日
柏拉文
越努力,越幸运

一、认识


Kubernetes 中,Service 外部访问指的是允许集群外部的用户或系统访问集群内的服务(Pods)。这种访问方式通常用于将内部服务暴露给外界,如访问 Web 应用、API 服务等。Kubernetes 提供以下几种方式来实现 Service 的外部访问:

  1. Ingress: IngressKubernetesHTTPHTTPS 路由入口,使用域名将外部请求转发到内部的 Service

  2. NodePort: 通过集群节点的某个固定端口(30000-32767 范围内)暴露 Service,外部用户可以通过 NodeIP:NodePort 访问。

  3. LoadBalancer: 通过云服务商的负载均衡器(如 AWS ELBGCP LB),直接向外暴露一个外部 IP 地址。

  4. ExternalName: 将 Kubernetes 内部服务映射到外部 DNS 名称,用于访问外部服务。

  5. Port Forwarding: 通过 kubectl port-forward 将本地机器的端口映射到 Pod

二、Ingress


Ingress: IngressKubernetesHTTPHTTPS 路由入口,使用域名将外部请求转发到内部的 Service。支持路径和主机路由,适合复杂架构。配置稍复杂,需要部署 Ingress Controller。适合需要基于域名访问服务,支持路径和主机路由规则,适合大型项目或微服务架构。结合 Ingress Controller(如 NginxTraefik)替代 NodePort/LoadBalancer,提供更灵活的路由控制。

2.1 部署 Service

1. 创建两个 ServiceDeployment: 用来模拟分别使用两个路径访问不同内容

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 ELBGCP 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