以下是一个完整的例子,展示了如何使用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。不同类型的服务具有不同的用途和行为:

  1. ClusterIP(默认)
    • 默认行为:如果不指定 type,Kubernetes 会默认将服务类型设置为 ClusterIP
    • 用途:只在 Kubernetes 集群内部可访问。其他 Pod 可以通过服务名称访问这个服务,但外部无法直接访问。
    • 典型场景:主要用于内部服务之间的通信,例如微服务架构中的服务之间的调用。
  2. NodePort
    • 行为:在每个节点上分配一个特定的端口(范围:30000-32767),通过这个端口可以从集群外部访问该服务。
    • 用途:适合在本地开发环境或简单的集群中使用,但不推荐在生产环境中直接使用。
    • 典型场景:本地开发和调试,或者需要从外部访问某个服务但没有负载均衡器时。
  3. LoadBalancer
    • 行为:向云提供商请求一个外部负载均衡器,通过负载均衡器可以从外部访问服务。
    • 用途:适用于在云环境中运行的生产系统。
    • 典型场景:在云环境中需要从外部访问的服务。
  4. ExternalName
    • 行为:将服务映射到指定的 DNS 名称,通过该名称可以访问外部服务。
    • 用途:适用于将 Kubernetes 服务代理到外部服务。
    • 典型场景:需要将内部服务请求转发到外部服务时。

不指定 type 的问题

如果不指定 type,默认的 ClusterIP 类型可能会导致以下问题:

  1. 无法从外部访问
    • ClusterIP 类型的服务只能在集群内部访问,外部无法直接访问这个服务。这可能会导致开发人员误以为服务已经暴露给外部,但实际上无法从外部访问。
  2. 调试和测试困难
    • 在本地开发和调试时,无法直接从本地机器访问 ClusterIP 服务,增加了调试和测试的复杂性。
  3. 误解和配置错误
    • 开发人员可能会误解服务的暴露方式,认为服务已经通过某种方式对外暴露,但实际上只是集群内部可访问。

如何正确指定 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或其他方法来暴露你的服务。