OpenShift 4 - Knative教程 (3) 了解Knative Serving的核心对象
《OpenShift 4.x HOL教程汇总》
说明:本文已经在OpenShift 4.13 + OpenShift Serverless 1.29.1环境中验证
Knative Serving的核心对象
一个 Knative 应用主要包括四类对象:Service(不同于Kubernetes的Service)、Route(类似但不是OpenShift的Route)、Configuration、Revision。
- Service(不同于Kubernetes的Service):它是一个集合,可以在Service中通过Template定义Knative的Route和Configuration对象。
- Configuration(类似OpenShift的DeploymentConfig): 创建并记录所有Revision的情况。用kn命令更新Service的时候实际就是在更新Configuration,而每次更新Configuration都会生成一个新的Revision。
- Revision:是一个特定的应用和配置环境的快照。该对象一旦生成就不可更改了(Immutable)。一个Revision对象对应一个Kubernetes Deployment对象。由于每次更新Configuration对象都会生成一个新的Revision,因此要不然每次都指定一个不同的Revision名称,要不就让Knative自动生成一个Revision名称。
- Route(类似但不是OpenShift的Route对象):Knative的Route是运行在也是用来做请求分发路由的,它是用Istio VirtualRoute实现,它定义了请求如何通过Traffic策略发给指定的Revision。蓝绿部署和金丝雀发布都是通过Route实现的。
无服务器应用的特点就是当没有外部请求的时候服务器是不需要运行Pod,只有在有请求的时候在启动Pod运行应用处理请求。在Knative中,这种按需的运行应用的效果是通过Activator和Autoscaler实现的。我们可以在OpenShift中的knative-serving项目中看到相关的支撑环境。
- 当首次通过Route访问Knative应用(假设此时还没有运行应用的Pod)的时候,请求将会先被Route发给Activator,Activator会激活目标Revision环境,Revision在通过Kubernetes Deployment启动Pod运行应用。这个过程完成了从无服务器到有服务器的过程,当有服务器运行Pod后就可以处理请求了。
- 当已经有运行应用的Pod的情况下,Route会直接将请求发给和Revsion对应的Pod。
- Autoscaler会监控Revision中的Pod运行其情况并收集Metrics数据,然后根据策略决定是扩展还是收缩Pod的数量。而扩展或收缩的动作是Revision通知Kubernetes的Deployment完成的。
创建Knative Serving应用
一个Knative Serving应用包括Service、Route、Configuration、Revision对象。他们的关系是Service=Route+Configuration,因此可以通过分别操作Route和Configuration或操作Service实现对Knative Serving应用的配置。
通过Configuration和Route实现蓝绿部署
- 创建新项目。
$ oc new-project kn-blue-green
- 创建名为blue-green-demo的Configuration对象,该对象使用的镜像是“knative-route-demo:blue”。
$ oc apply -f - << EOF
apiVersion: serving.knative.dev/v1
kind: Configuration
metadata:
name: blue-green-demo
spec:
template:
spec:
containers:
- image: svennam92/knative-route-demo:blue
env:
- name: T_VERSION
value: "blue"
EOF
- 查看项目中的对象,可以看到伴随Configuration还生成了Revision、Deployment、Replicset和Pod。其中Revision名为自动生成的blue-green-demo-jvtg7。
$ oc get all -n kn-blue-green
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/blue-green-demo-00001 ClusterIP 172.30.196.112 <none> 80/TCP 6m18s
service/blue-green-demo-00001-private ClusterIP 172.30.38.4 <none> 80/TCP,9090/TCP,9091/TCP,8022/TCP,8012/TCP 6m18s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/blue-green-demo-00001-deployment 0/0 0 0 6m18s
NAME DESIRED CURRENT READY AGE
replicaset.apps/blue-green-demo-00001-deployment-79867d6f57 0 0 0 6m18s
NAME LATESTCREATED LATESTREADY READY REASON
configuration.serving.knative.dev/blue-green-demo blue-green-demo-00001 blue-green-demo-00001 True
NAME CONFIG NAME K8S SERVICE NAME GENERATION READY REASON ACTUAL REPLICAS DESIRED REPLICAS
revision.serving.knative.dev/blue-green-demo-00001 blue-green-demo 1 True 0 0
- 创建Route对象。注意:需要将文件中的"revisionName"名称中的“blue-green-demo-XXX”替换为上一步创建的名为“blue-green-demo-00001”的Revision。
$ oc apply -f - << EOF
apiVersion: serving.knative.dev/v1
kind: Route
metadata:
name: blue-green-demo # The name of our route; appears in the URL to access the app
spec:
traffic:
- revisionName: blue-green-demo-00001 # replace XXX with your RevisionName
percent: 100 # All traffic goes to this revision
EOF
- 访问通过blue-green-demo的Route访问应用。确认返回页面中有“
App v1”。
$ curl -k $(kn route list blue-green-demo --no-headers | awk '{print $2}')
<!DOCTYPE html>
<html lang="en">
<head>
<title>Knative Routing Demo</title>
<link rel="stylesheet" type="text/css" href="/css/app.css" />
</head>
<body>
<div class="blue">App v1</div>
</div>
</body>
- 创建名为blue-green-demo的Configuration对象,该对象使用的镜像是“svennam92/knative-route-demo:green”。
$ oc apply -f - << EOF
apiVersion: serving.knative.dev/v1
kind: Configuration
metadata:
name: blue-green-demo # Configuration name is unchanged, since we're updating an existing Configuration
spec:
template:
spec:
containers:
- image: svennam92/knative-route-demo:green # URL to the new version of the sample app docker image
env:
- name: T_VERSION
value: "green" # Updated value for the T_VERSION environment variable
EOF
- 查看项目中对象的变化情况,确认已经有2个revision了。
$ oc get revision
NAME CONFIG NAME K8S SERVICE NAME GENERATION READY REASON ACTUAL REPLICAS DESIRED REPLICAS
blue-green-demo-00001 blue-green-demo 1 True 0 0
blue-green-demo-00002 blue-green-demo 2 True 0 0
- 更新Route对象,调整blue-green-demo-00001和blue-green-demo-00002的分配比例。
$ oc apply -f - << EOF
apiVersion: serving.knative.dev/v1
kind: Route
metadata:
name: blue-green-demo # Route name is unchanged, since we're updating an existing Route
spec:
traffic:
- revisionName: blue-green-demo-00001
percent: 0
- revisionName: blue-green-demo-00002
percent: 100
tag: v2 # A named route
EOF
- 访问通过blue-green-demo的Route访问应用。确认返回页面中有“
App v2”。
$ curl -k $(kn route list blue-green-demo --no-headers | awk '{print $2}')
<!DOCTYPE html>
<html lang="en">
<head>
<title>Knative Routing Demo</title>
<link rel="stylesheet" type="text/css" href="/css/app.css" />
</head>
<body>
<div class="green">App v2</div>
</div>
</body>
- 还可进一步调整Traffic比例,从而从green回退到blue版本,同时还可实现金丝雀发布。
通过Service部署应用
- 执行命令创建Service对象。
$ oc apply -f - << EOF
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: greeter
spec:
template:
metadata:
name: greeter-v1
spec:
containers:
- image: quay.io/rhdevelopers/knative-tutorial-greeter:quarkus
EOF
- 确认名为greeter的Knative Route已经是READY为True的状态。
$ kn route list greeter
NAME URL READY
greeter https://greeter-kn-blue-green.apps.cluster-jzmgb.jzmgb.sandbox866.opentlc.com True
- 通过Knative Route访问greeter应用。
$ curl -k $(kn route list greeter --no-headers | awk '{print $2}')
Hi greeter => '9861675f8845' : 1