Knative service 示例

发布时间: 更新时间: 总字数:2200 阅读时间:5m 作者: IP属地: 分享 复制网址

Knative service 增、删、改、查示例,并提供访问示例和Revision流量切分示例。

原理分析

在 Knative Serving 上,通过创建 Knative Service 对象来运行应用,Service 资源会触发创建如下资源:

  • 一个 Configuration 对象,它会创建一个 Revision,由 Revision 自动创建如下两个对象:
    • 一个 Deployment 对象
    • 一个 PodAutoscaler 对象
  • 一个 Route 对象,它会创建
    • 一个 Kubernetes Service 对象
    • 一个组成 Istio VirtualService 请求
      • <kservice-name>-ingress
      • <kservice-name>-mesh

命令介绍

kn service

kn-service--help
$ kn service --help
Manage Knative services

Usage:
  kn service [options]

Aliases:
  service, ksvc, services

Available Commands:
  apply       Apply a service declaration
  create      Create a service
  delete      Delete services
  describe    Show details of a service
  export      Export a service and its revisions
  import      Import a service and its revisions (experimental)
  list        List services
  update      Update a service


Use "kn <command> --help" for more information about a given command.
Use "kn options" for a list of global command-line options (applies to all commands).

创建 service

说明:

  • 官方的示例镜像太大,于是参考制作了 Golang 的镜像:xiexianbin/knative-helloworld-go:latest
  • service 创建有两种方式
    • 命令行方式
    • Yaml 文件方式

命令帮助

  • kn service create -h
kn-service-create-h
$ kn service create -h
Create a service

Usage:
  kn service create NAME --image IMAGE [options]

Examples:

  # Create a service 's0' using image knativesamples/helloworld
  kn service create s0 --image knativesamples/helloworld

  # Create a service with multiple environment variables
  kn service create s1 --env TARGET=v1 --env FROM=examples --image knativesamples/helloworld

  # Create or replace a service using --force flag
  # if service 's1' doesn't exist, it's a normal create operation
  kn service create --force s1 --image knativesamples/helloworld

  # Create or replace environment variables of service 's1' using --force flag
  kn service create --force s1 --env TARGET=force --env FROM=examples --image knativesamples/helloworld

  # Create a service with port 8080
  kn service create s2 --port 8080 --image knativesamples/helloworld

  # Create a service with port 8080 and port name h2c
  kn service create s2 --port h2c:8080 --image knativesamples/helloworld

  # Create or replace default resources of a service 's1' using --force flag
  # (earlier configured resource requests and limits will be replaced with default)
  # (earlier configured environment variables will be cleared too if any)
  kn service create --force s1 --image knativesamples/helloworld

  # Create a service with annotation
  kn service create s3 --image knativesamples/helloworld --annotation sidecar.istio.io/inject=false

  # Create a private service (that is a service with no external endpoint)
  kn service create s1 --image knativesamples/helloworld --cluster-local

  # Create a service with 250MB memory, 200m CPU requests and a GPU resource limit
  # [https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/]
  # [https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/]
  kn service create s4gpu --image knativesamples/hellocuda-go --request memory=250Mi,cpu=200m --limit nvidia.com/gpu=1

  # Create the service in offline mode instead of kubernetes cluster (Beta)
  kn service create gitopstest -n test-ns --image knativesamples/helloworld --target=/user/knfiles
  kn service create gitopstest --image knativesamples/helloworld --target=/user/knfiles/test.yaml
  kn service create gitopstest --image knativesamples/helloworld --target=/user/knfiles/test.json
...

命令行创建

创建 service

$ root@k8s-master:~/knative# kn service create h1 --port 8080 --image xiexianbin/knative-helloworld-go:latest --env TARGET="Go Sample v1"
Creating service 'h1' in namespace 'default':

  0.082s The Route is still working to reflect the latest desired specification.
  0.119s Configuration "h1" is waiting for a Revision to become ready.
  0.149s ...
 63.095s ...
 63.307s Ingress has not yet been reconciled.
 63.894s Waiting for load balancer to be ready
 64.135s Ready to serve.

Service 'h1' created to latest revision 'h1-00001' is available at URL:
http://h1.default.example.com

使用 kn 查看资源

root@k8s-master:~/knative# kn service list
NAME   URL                             LATEST     AGE     CONDITIONS   READY   REASON
h1     http://h1.default.example.com   h1-00001   3m19s   3 OK / 3     True
root@k8s-master:~/knative# kn service describe h1
Name:       h1
Namespace:  default
Age:        35m
URL:        http://h1.default.example.com

Revisions:
  100%  @latest (h1-00001) [1] (35m)
        Image:     xiexianbin/knative-helloworld-go:latest (pinned to 649546)
        Replicas:  0/0

Conditions:
  OK TYPE                   AGE REASON
  ++ Ready                  37m
  ++ ConfigurationsReady    37m
  ++ RoutesReady            37m
root@k8s-master:~/knative# kubectl get kservice
NAME   URL                             LATESTCREATED   LATESTREADY   READY   REASON
h1     http://h1.default.example.com   h1-00001        h1-00001      True
root@k8s-master:~/knative# kubectl get configurations.serving.knative.dev
NAME   LATESTCREATED   LATESTREADY   READY   REASON
h1     h1-00001        h1-00001      True
root@k8s-master:~/knative# kn revision list
NAME       SERVICE   TRAFFIC   TAGS   GENERATION   AGE   CONDITIONS   READY   REASON
h1-00001   h1        100%             1            37m   3 OK / 4     True
root@k8s-master:~/knative# kn route list
NAME   URL                             READY
h1     http://h1.default.example.com   True

查看 k8s 的资源

root@k8s-master:~/knative# kubectl get all
NAME                       TYPE           CLUSTER-IP       EXTERNAL-IP                                            PORT(S)                                              AGE
service/h1                 ExternalName   <none>           knative-local-gateway.istio-system.svc.cluster.local   80/TCP                                               2m52s
service/h1-00001           ClusterIP      10.108.172.164   <none>                                                 80/TCP,443/TCP                                       3m49s
service/h1-00001-private   ClusterIP      10.100.223.182   <none>                                                 80/TCP,443/TCP,9090/TCP,9091/TCP,8022/TCP,8012/TCP   3m49s
service/kubernetes         ClusterIP      10.96.0.1        <none>                                                 443/TCP                                              44h

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/h1-00001-deployment   0/0     0            0           3m49s

NAME                                             DESIRED   CURRENT   READY   AGE
replicaset.apps/h1-00001-deployment-57578c7c6d   0         0         0       3m49s

NAME                                   LATESTCREATED   LATESTREADY   READY   REASON
configuration.serving.knative.dev/h1   h1-00001        h1-00001      True

NAME                           URL                             READY   REASON
route.serving.knative.dev/h1   http://h1.default.example.com   True

NAME                                    CONFIG NAME   K8S SERVICE NAME   GENERATION   READY   REASON   ACTUAL REPLICAS   DESIRED REPLICAS
revision.serving.knative.dev/h1-00001   h1                               1            True             0                 0

NAME                             URL                             LATESTCREATED   LATESTREADY   READY   REASON
service.serving.knative.dev/h1   http://h1.default.example.com   h1-00001        h1-00001      True

调整 istio

root@k8s-master:~/knative# kubectl -n istio-system get svc
NAME                    TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                                      AGE
istio-egressgateway     ClusterIP      10.100.182.135   <none>        80/TCP,443/TCP                               45h
istio-ingressgateway    LoadBalancer   10.96.242.187    <pending>     15021:30455/TCP,80:30999/TCP,443:32324/TCP   45h
istiod                  ClusterIP      10.102.235.99    <none>        15010/TCP,15012/TCP,443/TCP,15014/TCP        45h
knative-local-gateway   ClusterIP      10.110.183.92    <none>        80/TCP                                       8h
root@k8s-master:~/knative# kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort"}}'
service/istio-ingressgateway patched
root@k8s-master:~/knative# kubectl -n istio-system get svc
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                                      AGE
istio-egressgateway     ClusterIP   10.100.182.135   <none>        80/TCP,443/TCP                               45h
istio-ingressgateway    NodePort    10.96.242.187    <none>        15021:30455/TCP,80:30999/TCP,443:32324/TCP   45h
istiod                  ClusterIP   10.102.235.99    <none>        15010/TCP,15012/TCP,443/TCP,15014/TCP        45h
knative-local-gateway   ClusterIP   10.110.183.92    <none>        80/TCP                                       8h

访问应用

  • 容器外访问
root@k8s-master:~/knative# curl -H 'host: h1.default.example.com' --resolve h1.default.example.com:30999:127.0.0.1 http://h1.default.example.com:30999
Hello Go Sample v1!
root@k8s-master:~/knative# kubectl get pod
NAME                                   READY   STATUS    RESTARTS   AGE
h1-00001-deployment-57578c7c6d-vb2qc   2/2     Running   0          6s
  • 容器内访问
root@k8s-master:~/knative# kubectl run --image=busybox --restart=Never --rm -it --command -- sh
If you don't see a command prompt, try pressing enter.
/ # wget -q -O - http://h1.default
Hello Go Sample v1!
  • 通过 ingressgateway 和 knative-local-gateway 访问
root@k8s-master:~/knative# kubectl -n istio-system get svc
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                                      AGE
istio-egressgateway     ClusterIP   10.100.182.135   <none>        80/TCP,443/TCP                               45h
istio-ingressgateway    NodePort    10.96.242.187    <none>        15021:30455/TCP,80:30999/TCP,443:32324/TCP   45h
istiod                  ClusterIP   10.102.235.99    <none>        15010/TCP,15012/TCP,443/TCP,15014/TCP        45h
knative-local-gateway   ClusterIP   10.110.183.92    <none>        80/TCP                                       8h
root@k8s-master:~/knative# curl -H 'host: h1.default.example.com' 10.96.242.187
Hello Go Sample v1!
root@k8s-master:~/knative# curl -H 'host: h1.default.example.com' 10.110.183.92
Hello Go Sample v1!

此时,也可以查看到 pod 被自动创建,一段时间(默认 60s)不访问后,Pod 会自动释放(配置 --scale-min)。

更新应用

root@k8s-master:~/knative# kn service update h1 --port 8080 --image xiexianbin/knative-helloworld-go:latest --env TARGET="hello world"
Updating Service 'h1' in namespace 'default':

  0.041s The Configuration is still working to reflect the latest desired specification.
  8.762s Traffic is not yet migrated to the latest revision.
  8.858s Ingress has not yet been reconciled.
  8.988s Waiting for load balancer to be ready
  9.205s Ready to serve.

Service 'h1' updated to latest revision 'h1-00002' is available at URL:
http://h1.default.example.com
  • 查看 Revision 变化,新增了 h1-00002
root@k8s-master:~/knative# kn revision list
NAME       SERVICE   TRAFFIC   TAGS   GENERATION   AGE   CONDITIONS   READY   REASON
h1-00002   h1        100%             2            43s   4 OK / 4     True
h1-00001   h1                         1            58m   3 OK / 4     True
  • 访问应用,发现访问内容已经变为 Target 的信息
root@k8s-master:~/knative# curl -H 'host: h1.default.example.com' 10.110.183.92
Hello hello world!

流量切分

  • 切换流量 h1-00001=100
root@k8s-master:~/knative# kn service update h1 --traffic h1-00001=100
Updating Service 'h1' in namespace 'default':

  0.069s The Route is still working to reflect the latest desired specification.
  0.131s Ingress has not yet been reconciled.
  0.338s Waiting for load balancer to be ready
  0.442s Ready to serve.

Service 'h1' with latest revision 'h1-00002' (unchanged) is available at URL:
http://h1.default.example.com
root@k8s-master:~/knative# kn revision list
NAME       SERVICE   TRAFFIC   TAGS   GENERATION   AGE     CONDITIONS   READY   REASON
h1-00002   h1                         2            5m22s   3 OK / 4     True
h1-00001   h1        100%             1            63m     3 OK / 4     True

# 访问流量已经到 h1-00001 的版本
root@k8s-master:~/knative# curl -H 'host: h1.default.example.com' 10.110.183.92
Hello Go Sample v1!
root@k8s-master:~/knative# curl -H 'host: h1.default.example.com' 10.110.183.92
Hello Go Sample v1!
  • 切换流量 h1-00001=20h1-00002=80,发现流量按照 1:4 分流,且两个 revision 的 Pod 资源均被创建
root@k8s-master:~/knative# kn service update h1 --traffic h1-00001=20 --traffic h1-00002=80
Updating Service 'h1' in namespace 'default':

  0.064s The Route is still working to reflect the latest desired specification.
  0.162s Ingress has not yet been reconciled.
  0.306s Waiting for load balancer to be ready
  0.499s Ready to serve.

Service 'h1' with latest revision 'h1-00002' (unchanged) is available at URL:
http://h1.default.example.com
root@k8s-master:~/knative# kn revision list
NAME       SERVICE   TRAFFIC   TAGS   GENERATION   AGE     CONDITIONS   READY   REASON
h1-00002   h1        80%              2            7m58s   3 OK / 4     True
h1-00001   h1        20%              1            65m     3 OK / 4     True
root@k8s-master:~/knative# curl -H 'host: h1.default.example.com' 10.110.183.92
Hello hello world!
root@k8s-master:~/knative# curl -H 'host: h1.default.example.com' 10.110.183.92
Hello hello world!
root@k8s-master:~/knative# curl -H 'host: h1.default.example.com' 10.110.183.92
Hello hello world!
root@k8s-master:~/knative# curl -H 'host: h1.default.example.com' 10.110.183.92
Hello hello world!
root@k8s-master:~/knative# curl -H 'host: h1.default.example.com' 10.110.183.92
Hello Go Sample v1!
root@k8s-master:~/knative# kubectl get pod
NAME                                   READY   STATUS        RESTARTS   AGE
h1-00001-deployment-57578c7c6d-klrs8   2/2     Terminating   0          99s
h1-00002-deployment-69fbb846f8-p78pc   2/2     Terminating   0          116s

流量切分原理

流量通过 Istio Virtual Service 的配置进行切分

revision-update-istio-virtualservices
root@k8s-master:~/knative# kubectl get virtualservices.networking.istio.io
NAME         GATEWAYS                                                                              HOSTS                                                                                     AGE
h1-ingress   ["knative-serving/knative-ingress-gateway","knative-serving/knative-local-gateway"]   ["h1.default","h1.default.example.com","h1.default.svc","h1.default.svc.cluster.local"]   67m
h1-mesh      ["mesh"]                                                                              ["h1.default","h1.default.svc","h1.default.svc.cluster.local"]                            67m
root@k8s-master:~/knative# kubectl describe virtualservices.networking.istio.io h1-ingress
Name:         h1-ingress
Namespace:    default
Labels:       networking.internal.knative.dev/ingress=h1
              serving.knative.dev/route=h1
              serving.knative.dev/routeNamespace=default
Annotations:  networking.internal.knative.dev/rollout: {}
              networking.knative.dev/ingress.class: istio.ingress.networking.knative.dev
              serving.knative.dev/creator: kubernetes-admin
              serving.knative.dev/lastModifier: kubernetes-admin
API Version:  networking.istio.io/v1beta1
Kind:         VirtualService
Metadata:
  Creation Timestamp:  2022-09-01T08:00:50Z
  Generation:          4
  Managed Fields:
    API Version:  networking.istio.io/v1alpha3
    Fields Type:  FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .:
          f:networking.internal.knative.dev/rollout:
          f:networking.knative.dev/ingress.class:
          f:serving.knative.dev/creator:
          f:serving.knative.dev/lastModifier:
        f:labels:
          .:
          f:networking.internal.knative.dev/ingress:
          f:serving.knative.dev/route:
          f:serving.knative.dev/routeNamespace:
        f:ownerReferences:
          .:
          k:{"uid":"dd10d69f-d4f9-4da8-8af6-cde2c76ef7e1"}:
      f:spec:
        .:
        f:gateways:
        f:hosts:
        f:http:
    Manager:    controller
    Operation:  Update
    Time:       2022-09-01T09:05:29Z
  Owner References:
    API Version:           networking.internal.knative.dev/v1alpha1
    Block Owner Deletion:  true
    Controller:            true
    Kind:                  Ingress
    Name:                  h1
    UID:                   dd10d69f-d4f9-4da8-8af6-cde2c76ef7e1
  Resource Version:        300603
  UID:                     f3a4872c-6b32-48ec-9d47-f6af6e5d33d5
Spec:
  Gateways:
    knative-serving/knative-ingress-gateway
    knative-serving/knative-local-gateway
  Hosts:
    h1.default
    h1.default.example.com
    h1.default.svc
    h1.default.svc.cluster.local
  Http:
    Headers:
      Request:
        Set:
          K - Network - Hash:  b82ea58fa335ea6a5a3cf2bc925acbbcb3c8c0f9b67e988f3ef3f3d1afb1c7a7
    Match:
      Authority:
        Prefix:  h1.default
      Gateways:
        knative-serving/knative-local-gateway
      Headers:
        K - Network - Hash:
          Exact:  override
    Retries:
    Route:
      Destination:
        Host:  h1-00001.default.svc.cluster.local
        Port:
          Number:  80
      Headers:
        Request:
          Set:
            Knative - Serving - Namespace:  default
            Knative - Serving - Revision:   h1-00001
      Weight:                               20
      Destination:
        Host:  h1-00002.default.svc.cluster.local
        Port:
          Number:  80
      Headers:
        Request:
          Set:
            Knative - Serving - Namespace:  default
            Knative - Serving - Revision:   h1-00002
      Weight:                               80
    Match:
      Authority:
        Prefix:  h1.default
      Gateways:
        knative-serving/knative-local-gateway
    Retries:
    Route:
      Destination:
        Host:  h1-00001.default.svc.cluster.local
        Port:
          Number:  80
      Headers:
        Request:
          Set:
            Knative - Serving - Namespace:  default
            Knative - Serving - Revision:   h1-00001
      Weight:                               20
      Destination:
        Host:  h1-00002.default.svc.cluster.local
        Port:
          Number:  80
      Headers:
        Request:
          Set:
            Knative - Serving - Namespace:  default
            Knative - Serving - Revision:   h1-00002
      Weight:                               80
    Headers:
      Request:
        Set:
          K - Network - Hash:  b82ea58fa335ea6a5a3cf2bc925acbbcb3c8c0f9b67e988f3ef3f3d1afb1c7a7
    Match:
      Authority:
        Prefix:  h1.default.example.com
      Gateways:
        knative-serving/knative-ingress-gateway
      Headers:
        K - Network - Hash:
          Exact:  override
    Retries:
    Route:
      Destination:
        Host:  h1-00001.default.svc.cluster.local
        Port:
          Number:  80
      Headers:
        Request:
          Set:
            Knative - Serving - Namespace:  default
            Knative - Serving - Revision:   h1-00001
      Weight:                               20
      Destination:
        Host:  h1-00002.default.svc.cluster.local
        Port:
          Number:  80
      Headers:
        Request:
          Set:
            Knative - Serving - Namespace:  default
            Knative - Serving - Revision:   h1-00002
      Weight:                               80
    Match:
      Authority:
        Prefix:  h1.default.example.com
      Gateways:
        knative-serving/knative-ingress-gateway
    Retries:
    Route:
      Destination:
        Host:  h1-00001.default.svc.cluster.local
        Port:
          Number:  80
      Headers:
        Request:
          Set:
            Knative - Serving - Namespace:  default
            Knative - Serving - Revision:   h1-00001
      Weight:                               20
      Destination:
        Host:  h1-00002.default.svc.cluster.local
        Port:
          Number:  80
      Headers:
        Request:
          Set:
            Knative - Serving - Namespace:  default
            Knative - Serving - Revision:   h1-00002
      Weight:                               80
Events:                                     <none>

Yaml 文件创建

Knative Service 资源(简称 kservice 或 ksvc)的定义主要由两个字段组成(和k8s其他的类似):

  • template:用于创建或更新 Configuration,且任何更新都会创建新的 Revision 对象
  • traffic:用于创建或更新 Route 对象
  • 示例
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    spec:
      containers:
        - image: xiexianbin/knative-helloworld-go:latest
          ports:
            - containerPort: 8080
          env:
            - name: TARGET
              value: "Go Sample v1"
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数