导读
Knative 是一款基于 Kubernetes 之上的开源 Serverless 框架,其目标之一是降低用户服务部署及使用门槛。在此基础上提还供了其它丰富的功能,如自动扩缩容,路由流量,金丝雀发布以及事件驱动等。在本文中,我们首先 Kubernetes 上部署应用并进行服务访问,然后在 Knative 中部署同样的服务并访问,以此对比来看Knative如何降低了服务部署及访问的门槛。
我们清楚如果提供一个线上对外访问的服务,一般需要提供域名访问入口,另外服务发现/负载均衡以及工作负载也是必须的,那么要提供这些能力,我们先看一下在Kubernetes中应该怎么做。
在 Kubernetes 提供域名服务访问
在kubernetes中,我们提供对外访问的服务,需要创建如下3个资源:
• Ingress - 域名访问
• Service - 服务发现/负载均衡
• Deployment/Statefulset等 - 工作负载
以最简单的部署 hello-world 为例,首先我们创建工作负载 Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world-deployment
labels:
app: hello-world
spec:
selector:
matchLabels:
app: hello-world
replicas: 2
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: registry.cn-hangzhou.aliyuncs.com/knative-sample/helloworld-go:73fbdd56
ports:
- name: http
containerPort: 8080
env:
- name: TARGET
value: "Go Sample v1"
将上面的文本保存hello_deployment.yaml, 然后执行 kubectl apply :
$ kubectl apply -f hello_deployment.yaml
我们可以看到两个 POD 已经 running 状态:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-world-deployment-86923fxfs-4wfw 1/1 Running 0 30s
hello-world-deployment-86923fxfs-xsr 1/1 Running 0 30s
接下来,我们创建服务访问 Service:
apiVersion: v1
kind: Service
metadata:
name: hello-world
spec:
selector:
app: hello-world
type: ClusterIP
ports:
- port: 80
targetPort: 8080
name: http
执行 kubectl 创建 service 如下:
$ kubectl apply -f hello_k8s_svc.yaml
最后我们将服务通过网关提供出来,那么需要Ingress, 通常的使用nginx ingress, 关于部署nginx ingress controller, 这里不进行详细说明,可以参考社区的部署方式即可: https://github.com/kubernetes/ingress-nginx.
部署完 nginx ingress controller 之后,我们创建ingress, 具体yaml内容如下:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: hello-world
spec:
rules:
- host: helloworld-go.knative.top
http:
paths:
- path: /
backend:
serviceName: hello-world
servicePort: 80
执行kubectl之后,将helloworld-go.knative.top
设置域名解析(nginx ingress controller slb)之后我们直接进行域名访问:
$ curl helloworld-go.knative.top
Hello Go Sample v1!
在 Knative 中提供域名服务访问
在 Knative 中提供域名访问你只需要创建 Knative Service 服务即可,最直接的理解就是:Knative Service = ingress + k8s service + deployment。此外Knative 提供了丰富的网关插件,如istio、kourier等。
一个简单的 Knative Service yaml:
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go
namespace: default
spec:
template:
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/knative-sample/helloworld-go:73fbdd56
env:
- name: TARGET
value: "Go Sample v1"
看起来是不是跟Deployment很像,其实这里面的spec,就是pod spec,对于直接对K8s工作负载比较熟悉的来说,使用Knative Service可以说是0门槛。
接下来通过执行 kubectl 创建该资源:
$ kubectl apply -f ksvc.yaml
我们可以看到Pod已经创建出来了:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
helloworld-go-cdqm7-deployment-75b4dc8c9-xxzcw 2/2 Running 0 11s
接下来我们如何进行域名服务访问呢?很简单,通过查看Knative Sevice即可:
$ kubectl get ksvc
NAME URL LATESTCREATED LATESTREADY READY REASON
helloworld-go http://helloworld-go.default.knative.top helloworld-go-5c52g helloworld-go-5c52g True
设置域名解析到对应的网关slb(如果使用istio, 则直接获取istio-ingressgateway 对应的外网ip),通过 curl 直接访问域名:
$ curl helloworld-go.default.knative.top
Hello Go Sample v1!
总结
通过上面的示例对比,我们很直接看到:通过 Knative 可以更简单的部署并提供服务。Knative 如何做到这一点呢?其实就是将K8s原有的资源进行了封装,并抽象出来了Knative Service这个应用模型,在满足功能的情况下,收敛了用户的资源操作界面,降低了服务部署与访问的门槛。此外通过这个模型,还提供了多版本管理以及基于流量的灰度发布能力,至于这些,我们会在后续的文章中介绍,欢迎大家持续关注。