无状态服务
Guestbook

Example: Deploying PHP Guestbook application with Redis

本教程将向你展示如何使用 Kubernetes 和 Docker 构建并部署一个简单的(不适用于生产环境)多层 Web 应用程序。此示例包含以下组件:

💡
  • 一个单实例的 Redis 用于存储留言簿条目
  • 多个 Web 前端实例

Objectives

💡
  • 启动一个 Redis 主节点。
  • 启动两个 Redis 从节点。
  • 启动留言簿前端服务。
  • 暴露并查看前端服务。
  • 清理资源。

Before you begin

你需要拥有一个 Kubernetes 集群,并且必须将 kubectl 命令行工具配置为与你的集群进行通信。 建议在至少有两个不作为控制平面主机的节点的集群上运行本教程。 如果你还没有集群,你可以使用 Minikube 创建一个,或者你也可以使用以下这些 Kubernetes 在线实验环境之一:

你的 Kubernetes 服务器版本必须为 v1.14 或更高。 要检查版本,请输入 kubectl version 命令。

Start up the Redis Database

留言簿应用程序使用 Redis 来存储其数据。

Creating the Redis Deployment

下面给出的清单文件指定了一个 Deployment 控制器,该控制器会运行一个单副本的 Redis Pod。

# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-leader
  labels:
    app: redis
    role: leader
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
        role: leader
        tier: backend
    spec:
      containers:
      - name: leader
        image: "docker.io/redis:6.0.5"
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 6379

1.在你下载清单文件的目录中打开一个终端窗口。

2.根据 redis-leader-deployment.yaml 文件应用 Redis Deployment:

kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-deployment.yaml

3.查询 Pod 列表以验证 Redis Pod 是否正在运行:

kubectl get pods

响应应该类似于以下内容:

NAME                           READY   STATUS    RESTARTS   AGE
redis-leader-fb76b4755-xjr2n   1/1     Running   0          13s

4.运行以下命令来查看 Redis leader Pod ( Redis主节点 )的日志:

kubectl logs -f deployment/redis-leader

Creating the Redis leader Service

留言簿应用程序需要与 Redis 进行通信以写入数据。你需要应用一个Service,将流量代理到 Redis Pod。Service定义了访问 Pod 的策略。

# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion: v1
kind: Service
metadata:
  name: redis-leader
  labels:
    app: redis
    role: leader
    tier: backend
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis
    role: leader
    tier: backend

1.根据下面的 redis-leader-service.yaml 文件来应用 Redis Service:

kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-service.yaml

2.查询Service列表,以验证 Redis Service是否正在运行:

kubectl get service

响应应该与以下内容类似:

NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes     ClusterIP   10.0.0.1     <none>        443/TCP    1m
redis-leader   ClusterIP   10.103.78.24 <none>        6379/TCP   16s
💡

注意:

此清单文件会创建一个名为 redis-leader 的Service,该Service带有一组标签,这些标签与之前定义的标签相匹配,这样Service就能将网络流量路由到 Redis Pod。

Set up Redis followers

虽然 Redis 主节点只是一个 Pod,但你可以通过添加几个 Redis 从节点(即副本)来使其具备高可用性,并满足流量需求。

# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-follower
  labels:
    app: redis
    role: follower
    tier: backend
spec:
  replicas: 2
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
        role: follower
        tier: backend
    spec:
      containers:
      - name: follower
        image: us-docker.pkg.dev/google-samples/containers/gke/gb-redis-follower:v2
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 6379

1.根据下面的 redis-follower-deployment.yaml 文件来应用 Redis Deployment:

kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-deployment.yaml

2.通过查询 Pod 列表来验证两个 Redis 从节点副本是否正在运行:

kubectl get pods

3.响应应该类似如下内容:

NAME                             READY   STATUS    RESTARTS   AGE
redis-follower-dddfbdcc9-82sfr   1/1     Running   0          37s
redis-follower-dddfbdcc9-qrt5k   1/1     Running   0          38s
redis-leader-fb76b4755-xjr2n     1/1     Running   0          11m

Creating the Redis follower service

留言簿应用程序需要与 Redis follower进行通信以读取数据。为了让 Redis follower 能够被发现,你必须设置另一个Service。

# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion: v1
kind: Service
metadata:
  name: redis-follower
  labels:
    app: redis
    role: follower
    tier: backend
spec:
  ports:
    # the port that this service should serve on
  - port: 6379
  selector:
    app: redis
    role: follower
    tier: backend

1.根据下面的 redis-follower-service.yaml 文件应用 Redis Service:

kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-service.yaml

2.查询Service列表以验证 Redis Service是否正在运行:

kubectl get service

响应应该类似如下内容:

    NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    kubernetes       ClusterIP   10.96.0.1       <none>        443/TCP    3d19h
    redis-follower   ClusterIP   10.110.162.42   <none>        6379/TCP   9s
    redis-leader     ClusterIP   10.103.78.24    <none>        6379/TCP   6m10s
💡

注意:

此清单文件会创建一个名为 redis-follower 的Service,该Service带有一组与之前定义的标签相匹配的标签,这样服务就能将网络流量路由到 Redis Pod。

Set up and Expose the Guestbook Frontend

现在你的留言簿应用的 Redis 存储已经启动并运行,接下来启动留言簿的 Web 服务器。和 Redis follower一样,前端应用也是通过 Kubernetes 的 Deployment 来部署的。

留言簿应用使用 PHP 作为前端。它被配置为根据请求是读操作还是写操作,与 Redis follower Service或leader Service进行通信。前端对外提供一个 JSON 接口,并采用基于 jQuery - Ajax 的用户体验(UX)设计。

Creating the Guestbook Frontend Deployment

# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
        app: guestbook
        tier: frontend
  template:
    metadata:
      labels:
        app: guestbook
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5
        env:
        - name: GET_HOSTS_FROM
          value: "dns"
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 80

1.根据 frontend-deployment.yaml 文件应用前端Deployment:

kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml

2.查询Pod列表,验证前端应用是否被部署:

kubectl get pods -l app=guestbook -l tier=frontend

响应应该与以下内容类似:

NAME                        READY   STATUS    RESTARTS   AGE
frontend-85595f5bf9-5tqhb   1/1     Running   0          47s
frontend-85595f5bf9-qbzwm   1/1     Running   0          47s
frontend-85595f5bf9-zchwc   1/1     Running   0          47s

Creating the Frontend Service

你所应用的 Redis Service仅可在 Kubernetes 集群内部访问,因为服务的默认类型是 ClusterIP(集群内部 IP)。ClusterIP 为Service所指向的一组 Pod 提供一个单一的 IP 地址,该 IP 地址仅在集群内部可访问。

如果你希望外部访客能够访问你的留言簿,就必须将前端Service配置为对外可见,这样客户端就可以从 Kubernetes 集群外部请求该Service。不过,即使Service使用的是 ClusterIP,Kubernetes 用户也可以使用 kubectl port-forward 命令来访问该Service。

💡

注意:

一些云服务提供商,如谷歌计算引擎(Google Compute Engine)或谷歌 Kubernetes 引擎(Google Kubernetes Engine),支持外部负载均衡器。如果你的云服务提供商支持负载均衡器,并且你想使用它,请取消 type: LoadBalancer 这一行的注释。

# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  # if your cluster supports it, uncomment the following to automatically create
  # an external load-balanced IP for the frontend service.
  # type: LoadBalancer
  #type: LoadBalancer
  ports:
    # the port that this service should serve on
  - port: 80
  selector:
    app: guestbook
    tier: frontend

1.从 frontend-service.yaml 文件中应用前端Service:

kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml

2.查询Service列表以验证前端Service是否正在运行:

kubectl get services

响应应该与以下内容类似:

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
frontend         ClusterIP   10.97.28.230    <none>        80/TCP     19s
kubernetes       ClusterIP   10.96.0.1       <none>        443/TCP    3d19h
redis-follower   ClusterIP   10.110.162.42   <none>        6379/TCP   5m48s
redis-leader     ClusterIP   10.103.78.24    <none>        6379/TCP   11m

Viewing the Frontend Service via kubectl port-forward

1.运行以下命令,将你本地机器上的 8080 端口转发到Service的 80 端口。

kubectl port-forward svc/frontend 8080:80

响应应该与以下内容类似:

    Forwarding from 127.0.0.1:8080 -> 80
    Forwarding from [::1]:8080 -> 80

2.在你的浏览器中打开网址 http://localhost:8080,即可查看留言簿。 (opens in a new tab)

Viewing the Frontend Service via LoadBalancer

1.运行以下命令来获取前端Service的 IP 地址。

kubectl get service frontend

响应应该与以下内容类似:

NAME       TYPE           CLUSTER-IP      EXTERNAL-IP        PORT(S)        AGE
frontend   LoadBalancer   10.51.242.136   109.197.92.229     80:32372/TCP   1m

2.复制外部 IP 地址,并在浏览器中打开该地址对应的页面,以查看你的留言簿。

💡

注意:

尝试输入一条消息,然后点击 “提交” 来添加一些留言簿条目。你输入的消息会显示在前端界面上。这表明数据已通过你之前创建的Service成功添加到 Redis 中。

Scale the Web Frontend

由于你的服务器被定义为使用Deployment controller的服务,因此你可以根据需要进行扩缩容操作。

1.运行以下命令来增加前端 Pod 的数量:

kubectl scale deployment frontend --replicas=5

2.查询 Pod 列表以验证正在运行的前端 Pod 的数量:

kubectl get pods

响应应该与以下内容类似:

NAME                             READY   STATUS    RESTARTS   AGE
frontend-85595f5bf9-5df5m        1/1     Running   0          83s
frontend-85595f5bf9-7zmg5        1/1     Running   0          83s
frontend-85595f5bf9-cpskg        1/1     Running   0          15m
frontend-85595f5bf9-l2l54        1/1     Running   0          14m
frontend-85595f5bf9-l9c8z        1/1     Running   0          14m
redis-follower-dddfbdcc9-82sfr   1/1     Running   0          97m
redis-follower-dddfbdcc9-qrt5k   1/1     Running   0          97m
redis-leader-fb76b4755-xjr2n     1/1     Running   0          108m

3.运行以下命令来减少前端 Pod 的数量:

kubectl scale deployment frontend --replicas=2

4.查询 Pod 列表以验证正在运行的前端 Pod 的数量:

kubectl get pods

响应应该与以下内容类似:

NAME                             READY   STATUS    RESTARTS   AGE
frontend-85595f5bf9-cpskg        1/1     Running   0          16m
frontend-85595f5bf9-l9c8z        1/1     Running   0          15m
redis-follower-dddfbdcc9-82sfr   1/1     Running   0          98m
redis-follower-dddfbdcc9-qrt5k   1/1     Running   0          98m
redis-leader-fb76b4755-xjr2n     1/1     Running   0          109m

Cleaning up

删除Deployments和Services也会一并删除所有正在运行的 Pod。你可以利用标签来通过一条命令删除多个资源。

1.运行以下命令来删除所有的 Pod、Deployment和Service。

kubectl delete deployment -l app=redis
kubectl delete service -l app=redis
kubectl delete deployment frontend
kubectl delete service frontend

响应应该与以下内容类似:

deployment.apps "redis-follower" deleted
deployment.apps "redis-leader" deleted
deployment.apps "frontend" deleted
service "frontend" deleted

2.查询 Pod 列表,以验证是否没有 Pod 正在运行:

kubectl get pods

响应应该与以下内容类似:

No resources found in default namespace.