此场景说明如何使用 Kubernetes 和 Docker 启动简单的多层 Web 应用程序。留言簿示例应用程序通过 Javascript API 调用将访客的笔记存储在 Redis 中。Redis 包含一个 master(用于存储)和一组复制的 redis ‘slaves’。
1.1 检查集群controlplane $ kubectl cluster-info Kubernetes master is running at https://172.17.0.29:6443 KubeDNS is running at https://172.17.0.29:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. controlplane $ kubectl get nodes NAME STATUS ROLES AGE VERSION controlplane Ready master 2m57s v1.14.0 node01 Ready1.2 创建rc2m31s v1.14.0
controlplane $ cat redis-master-controller.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: redis-master
labels:
name: redis-master
spec:
replicas: 1
selector:
name: redis-master
template:
metadata:
labels:
name: redis-master
spec:
containers:
- name: master
image: redis:3.0.7-alpine
ports:
- containerPort: 6379
创建
controlplane $ kubectl create -f redis-master-controller.yaml replicationcontroller/redis-master created controlplane $ kubectl get rc NAME DESIRED CURRENT READY AGE redis-master 1 1 0 2s controlplane $ kubectl get pods NAME READY STATUS RESTARTS AGE redis-master-2j4qm 1/1 Running 0 4s1.3 Redis 主服务
第二部分是服务。Kubernetes 服务是一种命名负载均衡器,它将流量代理到一个或多个容器。即使容器位于不同的节点上,代理也能工作。
服务代理在集群内通信,很少将端口暴露给外部接口。
当您启动服务时,您似乎无法使用 curl 或 netcat 进行连接,除非您将其作为 Kubernetes 的一部分启动。推荐的方法是使用 LoadBalancer 服务来处理外部通信。]
controlplane $ cat redis-master-service.yaml
apiVersion: v1
kind: Service
metadata:
name: redis-master
labels:
name: redis-master
spec:
ports:
# the port that this service should serve on
- port: 6379
targetPort: 6379
selector:
name: redis-master
创建
controlplane $ kubectl create -f redis-master-service.yaml service/redis-master created controlplane $ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.11.4 rc slave Pod443/TCP 6m58s redis-master ClusterIP 10.111.64.45 6379/TCP 1s controlplane $ kubectl describe services redis-master Name: redis-master Namespace: default Labels: name=redis-master Annotations: Selector: name=redis-master Type: ClusterIP IP: 10.111.64.45 Port: 6379/TCP TargetPort: 6379/TCP Endpoints: 10.32.0.193:6379 Session Affinity: None Events:
在这个例子中,我们将运行 Redis Slaves,它会从 master 复制数据。有关 Redis 复制的更多详细信息,请访问http://redis.io/topics/replication
如前所述,控制器定义了服务的运行方式。在这个例子中,我们需要确定服务如何发现其他 pod。YAML 将GET_HOSTS_FROM属性表示为 DNS。您可以将其更改为在 yaml 中使用环境变量,但这会引入创建顺序依赖关系,因为需要运行服务才能定义环境变量。
在这种情况下,我们将使用image:kubernetes/redis-slave:v2启动 pod 的两个实例。它将通过 DNS链接到redis-master。
controlplane $ cat redis-slave-controller.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: redis-slave
labels:
name: redis-slave
spec:
replicas: 2
selector:
name: redis-slave
template:
metadata:
labels:
name: redis-slave
spec:
containers:
- name: worker
image: gcr.io/google_samples/gb-redisslave:v1
env:
- name: GET_HOSTS_FROM
value: dns
# If your cluster config does not include a dns service, then to
# instead access an environment variable to find the master
# service's host, comment out the 'value: dns' line above, and
# uncomment the line below.
# value: env
ports:
- containerPort: 6379
执行:
controlplane $ kubectl create -f redis-slave-controller.yaml replicationcontroller/redis-slave created controlplane $ kubectl get rc NAME DESIRED CURRENT READY AGE redis-master 1 1 1 4m29s redis-slave 2 2 2 3s1.5 Redis slave service
和以前一样,我们需要让我们的奴隶可以访问传入的请求。这是通过启动一个知道如何与redis-slave通信的服务来完成的。
因为我们有两个复制的 Pod,该服务还将在两个节点之间提供负载平衡。
controlplane $ cat redis-slave-service.yaml
apiVersion: v1
kind: Service
metadata:
name: redis-slave
labels:
name: redis-slave
spec:
ports:
# the port that this service should serve on
- port: 6379
selector:
name: redis-slave
执行:
controlplane $ kubectl create -f redis-slave-service.yaml controlplane $ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.11.6 前端 rc443/TCP 14m redis-master ClusterIP 10.111.64.45 6379/TCP 7m13s redis-slave ClusterIP 10.109.135.21 6379/TCP 41s
启动数据服务后,我们现在可以部署 Web 应用程序。部署 Web 应用程序的模式与我们之前部署的 pod 相同。YAML 定义了一个名为 frontend 的服务,该服务使用图像 _gcr.io/google samples/gb-frontend:v3。复制控制器将确保三个 Pod 始终存在。
controlplane $ cat frontend-controller.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: frontend
labels:
name: frontend
spec:
replicas: 3
selector:
name: frontend
template:
metadata:
labels:
name: frontend
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
env:
- name: GET_HOSTS_FROM
value: dns
# If your cluster config does not include a dns service, then to
# instead access environment variables to find service host
# info, comment out the 'value: dns' line above, and uncomment the
# line below.
# value: env
ports:
- containerPort: 80
执行
controlplane $ kubectl create -f frontend-controller.yaml replicationcontroller/frontend created controlplane $ kubectl get rc NAME DESIRED CURRENT READY AGE frontend 3 3 1 2s redis-master 1 1 1 20m redis-slave 2 2 2 15m controlplane $ kubectl get pods NAME READY STATUS RESTARTS AGE frontend-bkcsj 1/1 Running 0 3s frontend-ftjrk 1/1 Running 0 3s frontend-jnckp 1/1 Running 0 3s redis-master-2j4qm 1/1 Running 0 20m redis-slave-79w2b 1/1 Running 0 15m redis-slave-j8zqj 1/1 Running 0 15m
PHP 代码使用 HTTP 和 JSON 与 Redis 通信。当设置一个值时,请求转到redis-master,而读取的数据来自redis-slave节点。
1.7 Guestbook Frontend Service为了使前端可访问,我们需要启动一个服务来配置代理。
YAML 将服务定义为NodePort。NodePort 允许您设置在整个集群中共享的知名端口。这就像Docker 中的-p 80:80。
在这种情况下,我们定义我们的 Web 应用程序在端口 80 上运行,但我们将在30080上公开服务。
controlplane $ cat frontend-service.yaml
apiVersion: v1
kind: Service
metadata:
name: frontend
labels:
name: 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: NodePort
ports:
# the port that this service should serve on
- port: 80
nodePort: 30080
selector:
name: frontend
controlplane $ kubectl create -f frontend-service.yaml
service/frontend created
controlplane $ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend NodePort 10.105.214.152 80:30080/TCP 2s
kubernetes ClusterIP 10.96.0.1 443/TCP 28m
redis-master ClusterIP 10.111.64.45 6379/TCP 21m
redis-slave ClusterIP 10.109.135.21 6379/TCP 15m
1.8 Access Guestbook Frontend
定义了所有控制器和服务后,Kubernetes 将开始将它们作为 Pod 启动。根据发生的情况,Pod 可以具有不同的状态。例如,如果 Docker 镜像仍在下载,则 Pod 将处于挂起状态,因为它无法启动。准备就绪后,状态将更改为running。
查看 Pod 状态
controlplane $ kubectl get pods NAME READY STATUS RESTARTS AGE frontend-bkcsj 1/1 Running 0 4m55s frontend-ftjrk 1/1 Running 0 4m55s frontend-jnckp 1/1 Running 0 4m55s redis-master-2j4qm 1/1 Running 0 24m redis-slave-79w2b 1/1 Running 0 20m redis-slave-j8zqj 1/1 Running 0 20m
查找节点端口
controlplane $ kubectl describe service frontend | grep NodePort Type: NodePort NodePort:30080/TCP
查看用户界面
一旦 Pod 处于运行状态,您将能够通过端口 30080 查看 UI。使用 URL 查看页面 https://2886795293-30080-elsy05.environments.katacoda.com
在幕后,PHP 服务通过 DNS 发现 Redis 实例。您现在已经在 Kubernetes 上部署了一个有效的多层应用程序。
2. 网络介绍Kubernetes 具有先进的网络功能,允许 Pod 和服务在集群网络内部和外部进行通信。
在此场景中,您将学习以下类型的 Kubernetes 服务。
- 集群IP
- 目标端口
- 节点端口
- 外部 IP
- 负载均衡器
Kubernetes 服务是一个抽象,它定义了如何访问一组 Pod 的策略和方法。通过 Service 访问的 Pod 集基于标签选择器。
2.1 集群 IP


