原文作者:木環
原文連結:
https://developer.aliyun.com/article/726199Kubernetes 核心概念
1. 目标概述
本文介紹一個簡單的 K8s 上手應用,希望通過這個簡單的實踐讓大家對 K8s 的核心概念有更深入的了解。
- 鞏固 Kubernetes 的基本概念
- 學會使用 Kubernetes 部署一個标準的“多層(multi-tier)”應用
- 了解 Kubernetes 裡如何通過 Pod,Deployment,Service 等 API 原語描述“應用”
2. 實驗概覽
完成此實驗後,可以掌握的能力有:
本實驗主要在 Kubernetes 叢集上部署一個名叫 guestbook 留言簿的 CURD (增查改删)應用。guestbook 是 Kubernetes 社群的一個經典的應用示例,它有一個 Web 界面來讓使用者進行 CURD 操作,然後向一個 Redis 主節點寫入資料,從多個 Redics 從節點讀去資料。
實驗分以下幾個步驟:
- 建立 Redis 主節點
- 建立 Redis 從節點叢集
- 建立 guestbook 應用
- 将 guestbook 應用通過 Service 暴露出來并進行通路
- 水準擴充 guestbook 應用
3. 所需資源:
一個完備的 Kubernetes 叢集。您可以選擇阿裡雲容器服務Kubernetes(ACK)進行上手操作。
可以用 Minikube 快速啟動一個單節點叢集(國内建議使用Minikube 中國版),也可以用雲上的 Kubernetes 叢集。本次實驗示範将使用阿裡雲容器服務提供的 Kubernetes 叢集,版本為 1.12。
你可以使用使用 kubectl version 檢視你的叢集版本同實驗版本一緻。
4. 實驗詳情
4.1 建立 Redis 主節點
在這裡,我們使用一個叫做 Deployment 的 API 對象,來描述單執行個體的Redis 主節點。
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-master
labels:
app: redis
spec:
selector:
matchLabels:
app: redis
role: master
tier: backend
replicas: 1
template:
metadata:
labels:
app: redis
role: master
tier: backend
spec:
containers:
- name: master
image: registry.cn-hangzhou.aliyuncs.com/kubeapps/redis
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 6379
我們需要把這個上述内容儲存為本地 YAML 檔案,名叫:
redis-master-deployment.yaml
。這個檔案主要定義了兩個東西:第一,Pod 裡的容器的鏡像是 redis;第二,這個 Deployment 的執行個體數(replicas)是 1,即指啟動一個 Pod。
然後,我們使用 Kubernetes 的用戶端,執行如下操作:
$ kubectl apply -f redis-master-deployment.yaml
deployment.apps/redis-master created
這一步完成後,Kubernetes 就會按照這個 YAML 檔案裡的描述為你建立對應的 Pod。這種使用方式就是聲明式 API 的典型特征。
接下來,我們可以檢視到這個 Pod:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
redis-master-68979f4ddd-pg9cv 1/1 Running 0 49s
可以看到,Pod 已經進入了 Running 狀态,表示一切正常。這時,我們就可以檢視這個 Pod 裡的 Redis 的日志:
$ kubectl logs -f redis-master-68979f4ddd-pg9cv
1:C 26 Apr 2019 18:49:29.303 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 26 Apr 2019 18:49:29.303 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 26 Apr 2019 18:49:29.303 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
1:M 26 Apr 2019 18:49:29.304 * Running mode=standalone, port=6379.
1:M 26 Apr 2019 18:49:29.304 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:M 26 Apr 2019 18:49:29.304 # Server initialized
1:M 26 Apr 2019 18:49:29.304 * Ready to accept connections
4.2 為 Redis 主節點建立 Service
Kubernetes 裡要通路 Pod 最好通過 Service 的方式,這樣用戶端就不需要記錄 Pod 的 IP 位址了。我們的 guestbook 網站需要通路 Redis 主節點的 Pod,是以也要通過 Service 來做。這個 Service API 對象的定義如下所示:
apiVersion: v1
kind: Service
metadata:
name: redis-master
labels:
app: redis
role: master
tier: backend
spec:
ports:
- port: 6379
targetPort: 6379
selector:
app: redis
role: master
tier: backend
這個 Service 名叫 redis-master,它聲明用自己的 6379 端口代理 Pod 的 6379 端口。
我們還是把上述内容儲存成檔案然後讓 Kubernetes 為我們建立它:
$ kubectl apply -f redis-master-service.yaml
service/redis-master created
然後我們可以檢視一下這個 Service:
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 181d
redis-master ClusterIP 10.107.220.208 <none> 6379/TCP 9s
這時候,你就可以通過 10.107.220.208:6379 通路到這個 Redis 主節點。
4.3 建立 Redis 從節點叢集
我們這個示例中,有多個 Redis 從節點來共同響應讀請求。同樣的,我們還是通過 Deployment 來描述"一個服務由多個相同的 Pod 執行個體副本組成"這種語義。
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-slave
labels:
app: redis
spec:
selector:
matchLabels:
app: redis
role: slave
tier: backend
replicas: 2
template:
metadata:
labels:
app: redis
role: slave
tier: backend
spec:
containers:
- name: slave
image: registry.cn-hangzhou.aliyuncs.com/kubeapps/gb-redisslave:v1
resources:
requests:
cpu: 100m
memory: 100Mi
env:
- name: GET_HOSTS_FROM
value: env
ports:
- containerPort: 6379
在這個 Deployment 中,我們指定了
replicas: 2
,即這個 Deployment 會啟動兩個相同 Pod(Redis 從節點)。
此外,
gb-redisslave:v1
這個鏡像,會自動讀取
REDIS_MASTER_SERVICE_HOST
這個環境變量的值,也就是 Redis 主節點的 Service 位址,然後用它來組建叢集。這個環境變量是Kubernetes 自動根據 redis-master 這個 Service 名字,自動注入到叢集的每一個 Pod 當中的。
然後,我們建立 Redis 從節點:
$ kubectl apply -f redis-slave-deployment.yaml
deployment.apps/redis-slave created
這時候,我們就可以檢視這些從節點的狀态:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
redis-master-68979f4ddd-pg9cv 1/1 Running 0 17m
redis-slave-78b464f5cd-2kn7w 0/1 ContainerCreating 0 37s
redis-slave-78b464f5cd-582bk 0/1 ContainerCreating 0 37s
4.4 為 Redis 從節點建立 Service
類似的,為了讓 guestbook 應用通路上述 Redis 從節點,我們還需要為它們建立一個 Service。在Kubernetes 裡,Service 可以通過 selector 選擇代理多個 Pod,并且負責負載均衡。這個Service 内容如下所示:
apiVersion: v1
kind: Service
metadata:
name: redis-slave
labels:
app: redis
role: slave
tier: backend
spec:
ports:
- port: 6379
selector:
app: redis
role: slave
tier: backend
建立和檢視 Service( 注意:這裡 6379 端口使用了簡化寫法,就不需要寫明 targetPort 了):
$ kubectl apply -f redis-slave-svc.yaml
service/redis-slave created
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 181d
redis-master ClusterIP 10.107.220.208 <none> 6379/TCP 16m
redis-slave ClusterIP 10.101.244.239 <none> 6379/TCP 57s
這樣,你就可以通過 10.10.101.244:6379 通路到任何一個 Redis 從節點了。
4.5 建立 guestbook 應用
guestbook 應用本身,依然通過一個 Deployment 來描述,如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: guestbook
spec:
selector:
matchLabels:
app: guestbook
tier: frontend
replicas: 3
template:
metadata:
labels:
app: guestbook
tier: frontend
spec:
containers:
- name: php-redis
image: registry.cn-hangzhou.aliyuncs.com/kubeapps/gb-frontend:v4
resources:
requests:
cpu: 100m
memory: 100Mi
env:
- name: GET_HOSTS_FROM
value: env
ports:
- containerPort: 80
這個 YAML 定義了一個 3 副本的 Deployment,即 guestbook 應用會啟動 3 個 Pod。
我們還是通過同樣的步驟建立這個 Deployment:
$ kubectl apply -f frontend.yaml
deployment.apps/frontend created
檢視 Pod 的狀态:
$ kubectl get pods -l app=guestbook -l tier=frontend
NAME READY STATUS RESTARTS AGE
frontend-78d6c59f4-2x24x 1/1 Running 0 3m4s
frontend-78d6c59f4-7mz87 1/1 Running 0 3m4s
frontend-78d6c59f4-sw7f2 1/1 Running 0 3m4s
4.6 為 guestbook 應用建立 Service
為了能夠讓使用者通路到 guestbook,我們也需要為 guestbook 來建立一個 Service,進而把這個應用以服務的形式暴露出來給使用者使用。
而為了能夠讓 Kubernetes 叢集以外的使用者,這個 Service 就必須是一個外部可通路的 Service。這個在 Kubernetes 裡有幾種做法。在雲上最常見的,是 LoadBalancer 模式。
apiVersion: v1
kind: Service
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
# 自建叢集隻能使用 NodePort 模式
# type: NodePort
type: LoadBalancer
ports:
- port: 80
selector:
app: guestbook
tier: frontend
由于我的叢集由阿裡雲容器服務提供,是以像上面這樣直接用 LoadBalancer 模式即可。
$ kubectl apply -f frontend-service.yaml
$ kubectl get service frontend
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend ClusterIP 172.19.10.209 101.37.192.20 80:32372/TCP 1m
現在,你隻要用浏覽器打開 EXTERNAL-IP 對應的位址:
http://101.37.192.20:31323,就可以通路到這個部署好的 guestbook 應用了。
而如果你是自建叢集,那就隻能用 NodePort 模式來實驗(上面 YAML 的注釋已經給出了使用方法)。需要注意的是 NodePort 由于安全性問題,不建議在生産環境中使用。
4.7 水準擴充 guestbook 應用
要通過 Kubernetes 來水準擴充你的應用以響應更多的請求非常簡單,隻需要如下一條指令:
$ kubectl scale deployment frontend --replicas=5
deployment.extensions/frontend scaled
你就會立刻看到你的 guestbook 應用的執行個體從 3 個變成了 5 個:
$ kubectl get pods -l app=guestbook -l tier=frontend
NAME READY STATUS RESTARTS AGE
frontend-78d6c59f4-2x24x 1/1 Running 0 14m
frontend-78d6c59f4-7mz87 1/1 Running 0 14m
frontend-78d6c59f4-chxwd 1/1 Running 0 19s
frontend-78d6c59f4-jrvfx 1/1 Running 0 19s
frontend-78d6c59f4-sw7f2 1/1 Running 0 14m
“阿裡巴巴雲原生微信公衆号(ID:Alicloudnative)關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的技術公衆号。”