Computación sin servidor basada en OpenWhisk, parte 4

Computación sin servidor basada en OpenWhisk, parte 4

Este artículo concluye el ciclo de notas traducidas sobre OpenWhisk del autor Priti Desai. Hoy veremos el proceso de implementación de OpenWhisk sobre Kubernetes con comandos corregidos para que funcionen con las versiones actuales de las aplicaciones. También se describirá el proceso de ejecución de funciones de OpenWhisk utilizando Knative y TektonCD en Kubernetes con el entorno de ejecución Nodejs.

Implementando OpenWhisk en Kubernetes

Durante varios días, hice un experimento para implementar OpenWhisk en Kubernetes con el fin de crear un entorno simple y rápido para probar tareas. Como soy nueva en Kubernetes, creo que dediqué un día y medio para la implementación exitosa. En este el repositorio hay instrucciones muy claras para implementar OpenWhisk en Kubernetes. Aquí habrá instrucciones para la implementación, hechas para Mac (también estaré haciendo todo en Linux, porque prefiero Linux. — nota del traductor).

  1. Instalando el gestor de paquetes asdf, y luego lo solucionamos automáticamente ~/.bash_profile o su equivalente así:

$ brew install asdf
$ [ -s "/usr/local/opt/asdf/asdf.sh" ] && . /usr/local/opt/asdf/asdf.sh
$ source ~/.bash_profile

[En Linux, este paso no es necesario, aunque brew está disponible. — nota del traductor]

  1. Agregamos los plugins minikube y kubelet:

$ asdf plugin-add kubectl
$ asdf plugin-add minikube

[Nuevamente, saltamos este paso en Linux. — nota del traductor]

  1. Instalamos minikube y kubelet:

$ asdf install kubectl 1.9.0
$ asdf global kubectl 1.9.0
$ asdf install minikube 0.25.2
$ asdf global minikube 0.25.2

[se instalan versiones específicas, pero yo verifiqué todo con las últimas versiones disponibles para Linux; sospecho que se puede instalar la última sin problema. — nota del traductor]

En Linux, este paso se realiza aproximadamente así (todo se instala en ~/bin, que tengo en mi PATH, nota del traductor):

$ curl -L0 minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube && mv minikube ~/bin/
$ curl -L0 https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && chmod +x kubectl && mv kubectl ~/bin/

  1. Creamos una máquina virtual minikube (debe tener VirtualBox instalado previamente):

$ minikube start --cpus 2 --memory 4096 --kubernetes-version=v1.9.0 --extra-config=apiserver.Authorization.Mode=RBAC

[Todo funciona para mí con el comando minikube start , sin parámetros y con los valores por defecto. — nota del traductor]

$ minikube start
  minikube v1.5.2 en Debian 8.11
  Controlador 'virtualbox' seleccionado automáticamente
  Descargando imagen de arranque de la VM ...
    > minikube-v1.5.1.iso.sha256: 65 B / 65 B [--------------] 100.00% ? p/s 0s
    > minikube-v1.5.1.iso: 143.76 MiB / 143.76 MiB [-] 100.00% 5.63 MiB p/s 26s
  Creando VM en virtualbox (CPUs=2, Memoria=4096MB, Disco=20000MB) ...
  Preparando Kubernetes v1.16.2 en Docker '18.09.9' ...
  Descargando kubelet v1.16.2
  Descargando kubeadm v1.16.2
  Extrayendo imágenes ...
  Lanzando Kubernetes ...  Esperando: apiserver
  ¡Listo! kubectl ahora está configurado para usar "minikube"

  1. Cambiando la red en Docker a modo promiscuo:

$ minikube ssh -- sudo ip link set docker0 promisc on

  1. Creamos un namespace y etiquetamos el nodo de trabajo:

$ kubectl create namespace openwhisk
$ kubectl label nodes --all openwhisk-role=invoker

  1. Obtenemos el contenido del repositorio y redefinimos el tipo para ingress en el archivo mycluster.yaml:

$ git clone https://github.com/apache/incubator-openwhisk-deploy-kube.git
$ cd incubator-openwhisk-deploy-kube/
$ cat < mycluster.yaml
whisk:
    ingress:
        type: NodePort
            api_host_name: 192.168.99.100
            api_host_port: 31001
nginx:
    httpsNodePort: 31001
EOF

  1. Instalamos Helm y realizamos el despliegue con él:

$ brew install kubernetes-helm
$ helm init # init Helm Tiller, no necesario en Helm v3+
$ kubectl get pods -n kube-system # verifica que tiller-deploy esté en estado en ejecución, no necesario en helm v3+
$ kubectl create clusterrolebinding tiller-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default
$ helm install ./openwhisk/helm/ --namespace=openwhisk -f mycluster.yaml

[En Linux con las últimas versiones (se tenía disponible v3.0.1) será un poco diferente. — nota del traductor]

$ curl -L0 https://get.helm.sh/helm-v3.0.1-linux-amd64.tar.gz | tar -xzvf - linux-amd64/helm --strip-components=1; sudo mv helm /usr/local/bin
$ kubectl create clusterrolebinding tiller-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default
$ helm install ./openwhisk/helm/ --namespace=openwhisk --generate-name -f mycluster.yaml

  1. Verificamos que todo esté funcionando (ESTADO = Running o Completed):

$ kubectl get pods -n openwhisk
NOMBRE                                                             LISTO   ESTADO      REINICIOS   EDAD
openwhisk-1576070780-alarmprovider-6868dc694-plvpf                1/1     Ejecutándose  1          1d5h
openwhisk-1576070780-apigateway-8d56f4979-825hf                   1/1     Ejecutándose  1          1d5h
openwhisk-1576070780-cloudantprovider-544bb46596-9scph            1/1     Ejecutándose  1          1d5h
openwhisk-1576070780-controller-0                                 1/1     Ejecutándose  2          1d5h
openwhisk-1576070780-couchdb-7fd7f6c7cc-42tw6                     1/1     Ejecutándose  1          1d5h
openwhisk-1576070780-gen-certs-z9nsb                              0/1     Completado    0          1d5h
openwhisk-1576070780-init-couchdb-r2vmt                           0/1     Completado    0          1d5h
openwhisk-1576070780-install-packages-27dtr                       0/1     Completado    0          1d4h
openwhisk-1576070780-invoker-0                                    1/1     Ejecutándose  1          1d5h
openwhisk-1576070780-kafka-0                                      1/1     Ejecutándose  1          1d5h
openwhisk-1576070780-kafkaprovider-f8b4cf4fc-7z4gt                1/1     Ejecutándose  1          1d5h
openwhisk-1576070780-nginx-6dbdbf69bc-5x76n                       1/1     Ejecutándose  1          1d5h
openwhisk-1576070780-redis-cfd8756f4-hkrt6                        1/1     Ejecutándose  1          1d5h
openwhisk-1576070780-wskadmin                                     1/1     Ejecutándose  1          1d5h
openwhisk-1576070780-zookeeper-0                                  1/1     Ejecutándose  1          1d5h
wskopenwhisk-1576070780-invoker-00-1-prewarm-nodejs10             1/1     Ejecutándose  0          61s
wskopenwhisk-1576070780-invoker-00-2-prewarm-nodejs10             1/1     Ejecutándose  0          61s
wskopenwhisk-1576070780-invoker-00-3-whisksystem-invokerhealtht   1/1     Ejecutándose  0          59s

  1. Configuramos wsk para trabajar:

$ wsk property set --apihost 192.168.99.100:31001
$ wsk property set --auth 23bc46b1-71f6-4ed5-8c54-816aa4f8c502:123zO3xZCLrMN6v2BKK1dXYFpXlPkccOFqm12CdAsMgRU4VrNZ9lyGVCGuMDGIwP

Verificando:

$ wsk -i list
Entidades en el espacio de nombres: default
paquetes
acciones
triggers
reglas

Problemas y sus soluciones

getsockopt: conexión rehusada

$ wsk -i list
error: No se puede obtener la lista de entidades para el espacio de nombres 'default': Get http://192.168.99.100:31001/api/v1/namespaces/_/actions?limit=0&skip=0: dial tcp 192.168.99.100:31001: getsockopt: conexión rehusada

Verificamos que los contenedores en el namespace openwhisk estén en estado En ejecución, ya que a veces falla con errores CreateContainerConfigError.

Invoker aún inicializando — Init:1/2

El proceso de descarga de todo tipo de entornos de ejecución puede tardar mucho tiempo. Para acelerar, se puede indicar una lista mínima en el archivo mycluster.yaml:

whisk:
  runtimes: "runtimes-minimal-travis.json"

Contenedor con nombre -install-packages- sale con Error

Simplemente aumente los tiempos de espera para las pruebas de liveness.

Instalación de OpenWhisk sobre Knative

Priti Desai realizó la instalación sobre un clúster en la nube de IBM, así como en un minikube normal, utilizando Knative Build y BuildTemplates. Yo también estaré instalando sobre minikube, basado en cómo se describió En nuestro blog anteriormente, utilizando las versiones más recientes del software. Dado que Knative Build y BuildTemplates han sido oficialmente declarados obsoletos, usaré la recomendación de reemplazo en forma de Tekton Pipelines. La siguiente parte del artículo se escribió después de leer la documentación de Tekton Pipelines, pero se basa en las ideas de Priti. Para trabajar se necesitará acceso a algún Docker Registry; yo, al igual que el autor original, usaré DockerHub.

$ curl -L0 https://github.com/solo-io/gloo/releases/download/v1.2.10/glooctl-linux-amd64; chmod +x glooctl-linux-amd64; mv glooctl-linux-amd64 ~/bin
$ glooctl install knative
$ kubectl get pods -n knative-serving
NAME                              READY   STATUS    RESTARTS   AGE
activator-77fc555665-rvrst        1/1     Running   0          2m23s
autoscaler-5c98b7c9b6-x8hh4       1/1     Running   0          2m21s
autoscaler-hpa-5cfd4f6845-w87kq   1/1     Running   0          2m22s
controller-7fd74c8f67-tprm8       1/1     Running   0          2m19s
webhook-74847bb77c-txr2g          1/1     Running   0          2m17s
$ kubectl get pods -n gloo-system
NAME                                      READY   STATUS    RESTARTS   AGE
discovery-859d7fbc9c-8xhvh                1/1     Running   0          51s
gloo-545886d9c6-85mwt                     1/1     Running   0          51s
ingress-67d4996d75-lkkmw                  1/1     Running   0          50s
knative-external-proxy-767dfd656c-wwv2z   1/1     Running   0          50s
knative-internal-proxy-6fdddcc6b5-7vqd8   1/1     Running   0          51s

Computación sin servidor basada en OpenWhisk, parte 4
Construcción y operación de OpenWhisk sobre Knative

  1. Obtenemos el contenido de este repositorio:

$ git clone https://github.com/tektoncd/catalog/
$ cd catalog/openwhisk

  1. Configuramos los datos de acceso al Registry como variables de entorno y los guardamos como un secreto de Kubernetes:

$ export DOCKER_USERNAME=
$ export DOCKER_PASSWORD=
$ sed -e 's/${DOCKER_USERNAME}/'"$DOCKER_USERNAME"'/' -e 's/${DOCKER_PASSWORD}/'"$DOCKER_PASSWORD"'/' docker-secret.yaml.tmpl > docker-secret.yaml
$ kubectl apply -f docker-secret.yaml

Verificando:

$ kubectl get secret
NAME                    TYPE                                  DATA      AGE
dockerhub-user-pass     kubernetes.io/basic-auth              2         21s

  1. Creamos una cuenta para construir entornos:

$ kubectl apply -f service-account.yaml

Verificando:

$ kubectl get serviceaccount/openwhisk-runtime-builder
NAME                        SECRETS   AGE
openwhisk-runtime-builder   2         31m

  1. Creamos una tarea para construir la imagen para OpenWhisk

$ kubectl apply -f openwhisk.yaml
task.tekton.dev/openwhisk created

  1. Ejecutamos la tarea para construir la imagen (con un ejemplo de NodeJS):

Creamos un archivo taskrun.yaml con el contenido:

# Git Pipeline Resource for OpenWhisk NodeJS Runtime
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
    name: openwhisk-nodejs-runtime-git
spec:
    type: git
    params:
        - name: revision
          value: master
        - name: url
          value: https://github.com/apache/openwhisk-runtime-nodejs.git
---

# Image Pipeline Resource for OpenWhisk NodeJS Sample Application
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
    name: openwhisk-nodejs-helloworld-image
spec:
    type: image
    params:
        - name: url
          value: docker.io/${DOCKER_USERNAME}/openwhisk-nodejs-helloworld
---

# Task Run to build NodeJS image with the action source
apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
    name: openwhisk-nodejs-helloworld
spec:
    serviceAccountName: openwhisk-runtime-builder
    taskRef:
        name: openwhisk
    inputs:
        resources:
            - name: runtime-git
              resourceRef:
                name: openwhisk-nodejs-runtime-git
        params:
            - name: DOCKERFILE
              value: "./runtime-git/core/nodejs10Action/knative/Dockerfile"
            - name: OW_ACTION_NAME
              value: "nodejs-helloworld"
            - name: OW_ACTION_CODE
              value: "function main() {return {payload: 'Hello World!'};}"
            - name: OW_PROJECT_URL
              value: ""
    outputs:
        resources:
            - name: runtime-image
              resourceRef:
                name: openwhisk-nodejs-helloworld-image
---

Aplicamos los datos actuales para este archivo:

$ sed 's/${DOCKER_USERNAME}/'"$DOCKER_USERNAME"'/' -i taskrun.yaml

Aplicamos:

$ kubectl apply -f taskrun.yaml
pipelineresource.tekton.dev/openwhisk-nodejs-runtime-git created
pipelineresource.tekton.dev/openwhisk-nodejs-helloworld-image created
taskrun.tekton.dev/openwhisk-nodejs-helloworld created

La verificación del funcionamiento consiste en obtener el nombre del pod, ver su estado. También se puede revisar el registro de ejecución de cada paso, por ejemplo:

$ kubectl get taskrun
NAME                          SUCCEEDED   REASON      STARTTIME   COMPLETIONTIME
openwhisk-nodejs-helloworld   True        Succeeded   5m15s       44s
$ kubectl get pod openwhisk-nodejs-helloworld-pod-4640d3
NAME                                     READY   STATUS      RESTARTS   AGE
openwhisk-nodejs-helloworld-pod-4640d3   0/6     Completed   0          5m20s
$ kubectl logs openwhisk-nodejs-helloworld-pod-4640d3 -c step-git-source-openwhisk-nodejs-runtime-git-r8vhr
{"level":"info","ts":1576532931.5880227,"logger":"fallback-logger","caller":"logging/config.go:69","msg":"Fetch GitHub commit ID from kodata failed: open /var/run/ko/refs/heads/master: no such file or directory"}
{"level":"info","ts":1576532936.538926,"logger":"fallback-logger","caller":"git/git.go:81","msg":"Successfully cloned https://github.com/apache/openwhisk-runtime-nodejs.git @ master in path /workspace/runtime-git"}
{"level":"warn","ts":1576532936.5395331,"logger":"fallback-logger","caller":"git/git.go:128","msg":"Unexpected error: creating symlink: symlink /tekton/home/.ssh /root/.ssh: file exists"}
{"level":"info","ts":1576532936.8202565,"logger":"fallback-logger","caller":"git/git.go:109","msg":"Successfully initialized and updated submodules in path /workspace/runtime-git"}

Después de ejecutar, tendremos una imagen en el registro que puede ser desplegada usando la utilidad kn, diseñada para trabajar con servicios Knative, por ejemplo:

kn service create nodejs-helloworld --image docker.io/${DOCKER_USERNAME}/openwhisk-nodejs-helloworld
Servicio 'nodejs-helloworld' creado exitosamente en el namespace 'default'.
Esperando a que el servicio 'nodejs-helloworld' esté listo ... OK

URL del servicio:
http://nodejs-helloworld.default.example.com

En el caso de usar Gloo, puedes verificar la operatividad así:

$ curl -H "Host: nodejs-helloworld.default.example.com" -X POST $(glooctl proxy url --name knative-external-proxy)
{"OK":true}
$ curl -H "Host: nodejs-helloworld.default.example.com" -X POST $(glooctl proxy url --name knative-external-proxy)
{"payload":"¡Hola Mundo!"}

Otros artículos del ciclo

Computación sin servidor basada en OpenWhisk, parte 1
Computación sin servidor basada en OpenWhisk, parte 2
Computación sin servidor basada en OpenWhisk, parte 3
Computación sin servidor basada en OpenWhisk, parte 4

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster