以下是一个完整的例子,展示了如何使用Kubernetes部署一个简单的Web应用程序。这个例子包括一个Deployment和一个Service。
创建 Deployment
首先,创建一个名为webapp-deployment.yaml
的Deployment配置文件:
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-deployment
spec:
replicas: 2
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nginx:latest
ports:
- containerPort: 80
这个Deployment配置将创建一个名为webapp-deployment
的Deployment,它包含两个副本的Pods,每个Pod都运行一个Nginx容器,监听80端口。
创建 Service
接下来,创建一个名为webapp-service.yaml
的Service配置文件:
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
selector:
app: webapp
ports:
- protocol: TCP
port: 8088
targetPort: 80
type: LoadBalancer
这个 Service 配置将创建一个名为 webapp-service
的 Service,它将外部请求的 8088 端口转发到标签为app: webapp
的 Pods 的 80 端口。
type: LoadBalancer
指示云提供商为 Service 提供一个外部可访问的负载均衡器。
type 字段
type
字段指定了服务的暴露方式。默认情况下,如果不指定 type
,Kubernetes 会将其设置为 ClusterIP
。不同类型的服务具有不同的用途和行为:
- ClusterIP(默认):
- 默认行为:如果不指定
type
,Kubernetes 会默认将服务类型设置为ClusterIP
。 - 用途:只在 Kubernetes 集群内部可访问。其他 Pod 可以通过服务名称访问这个服务,但外部无法直接访问。
- 典型场景:主要用于内部服务之间的通信,例如微服务架构中的服务之间的调用。
- 默认行为:如果不指定
- NodePort:
- 行为:在每个节点上分配一个特定的端口(范围:30000-32767),通过这个端口可以从集群外部访问该服务。
- 用途:适合在本地开发环境或简单的集群中使用,但不推荐在生产环境中直接使用。
- 典型场景:本地开发和调试,或者需要从外部访问某个服务但没有负载均衡器时。
- LoadBalancer:
- 行为:向云提供商请求一个外部负载均衡器,通过负载均衡器可以从外部访问服务。
- 用途:适用于在云环境中运行的生产系统。
- 典型场景:在云环境中需要从外部访问的服务。
- ExternalName:
- 行为:将服务映射到指定的 DNS 名称,通过该名称可以访问外部服务。
- 用途:适用于将 Kubernetes 服务代理到外部服务。
- 典型场景:需要将内部服务请求转发到外部服务时。
不指定 type
的问题
如果不指定 type
,默认的 ClusterIP
类型可能会导致以下问题:
- 无法从外部访问:
ClusterIP
类型的服务只能在集群内部访问,外部无法直接访问这个服务。这可能会导致开发人员误以为服务已经暴露给外部,但实际上无法从外部访问。
- 调试和测试困难:
- 在本地开发和调试时,无法直接从本地机器访问
ClusterIP
服务,增加了调试和测试的复杂性。
- 在本地开发和调试时,无法直接从本地机器访问
- 误解和配置错误:
- 开发人员可能会误解服务的暴露方式,认为服务已经通过某种方式对外暴露,但实际上只是集群内部可访问。
如何正确指定 type
根据你的需求,正确指定 type
是非常重要的:
- 如果服务只需要在集群内部访问,使用默认的
ClusterIP
是合适的。 - 如果需要从外部访问服务,可以使用
NodePort
或LoadBalancer
。 - 如果需要将服务代理到外部 DNS 名称,使用
ExternalName
。
启动服务
现在,使用kubectl
命令来创建这些资源:
kubectl apply -f webapp-deployment.yaml
kubectl apply -f webapp-service.yaml
检查Deployment和Pods的状态:
kubectl get deployment webapp-deployment
kubectl get pods -l app=webapp
检查Service的状态,并获取外部访问的IP地址(如果是LoadBalancer类型):
kubectl get service webapp-service
如果一切正常,你应该能够看到Pods正在运行,Service已经分配了一个外部IP地址。你可以通过浏览器访问这个IP地址来查看Nginx的默认欢迎页面。
更新镜像
如果你需要更新应用程序,比如使用一个新版本的Nginx镜像,你只需要更新webapp-deployment.yaml
文件中的镜像标签,并重新应用配置:
containers:
- name: webapp
image: nginx:1.19.0 # 更新为新的镜像版本
ports:
- containerPort: 80
然后运行:
kubectl apply -f webapp-deployment.yaml
Kubernetes将执行滚动更新,逐步替换旧的Pods,而不会中断服务。
Ingress
Ingress 是允许访问到集群内 Service 的规则的集合,您可以通过配置转发规则,实现不同 URL 可以访问到集群内不同的 Service。
在 Kubernetes 中,Ingress 资源本身并不能直接指定暴露的端口。Ingress 资源的主要用途是定义 HTTP 和 HTTPS 路由规则,将外部流量通过 Ingress 控制器转发到集群内部的服务。默认情况下,Ingress 控制器会监听标准的 HTTP(80)和 HTTPS(443)端口。
kind:标识 Ingress 资源类型。
metadata:Ingress 的名称、Label 等基本信息。
metadata.annotations:Ingress 的额外说明,可通过该参数设置额外增强能力。
spec.rules:Ingress 的转发规则,配置该规则可实现简单路由服务、基于域名的简单扇出路由、简单路由默认域名、配置安全的路由服务等。
在云环境中,如果使用 LoadBalancer
类型的服务来暴露 Ingress 控制器,可以指定 LoadBalancer 服务的端口。例如:
# nginx-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: test.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
这种配置将流量路由到 nginx-service
的 80 端口并指定域名 test.com
最后
请记住,这个例子假设你已经有一个Kubernetes集群在运行,并且你的kubectl配置正确。如果你使用的是云服务提供商的Kubernetes服务,LoadBalancer类型的Service将自动为你创建一个外部负载均衡器。如果你在本地或没有负载均衡器的环境中运行,你可能需要使用NodePort或其他方法来暴露你的服务。