Knative is talked about a great deal, especially around how its capabilities can help provide more standard building blocks on top of Kubernetes for building microservices and serverless like services, e.g., scale to zero, and scale on demand. Knative high level has three capability areas: building, serving, and eventing. This post will provide some examples around Knative Build and Knative Serving with Solo.io Gloo.
Knative Serving initially included all of Istio only to use a small fraction of its capabilities around being a Kubernetes cluster ingress. Recently the Knative team added Solo.io Gloo as an alternative to Istio. More details are available in Gloo, Knative and the future of Serverless and Gloo, by Solo.io, is the first alternative to Istio on Knative.
This post shows a quick example of Knative Building, Knative Serving, and Gloo integration.
All of the Kubernetes Manifests are located in the following GitHub repository https://github.com/scranton/helloworld-knative. I encourage you to fork that repository to help you try these examples yourself.
Setup
These instructions assume you are running on a clean, recent minikube
install locally, and that you also have kubectl
available locally.
Install Gloo
On Mac or Linux, the quickest option is to use Homebrew. Full Gloo install instructions at Gloo documentation.
brew install glooctl
Then assuming you’ve got a running minikube
, and kubectl
set up against that minikube
instance, i.e., kubectl
config current-context
returns minikube
, run the following to install Gloo with Knative Serving.
glooctl install knative
Deploy existing example image
I’ve already built this example, and have hosted the image publicly in my Docker Hub repository. To use Knative to serve up this existing image, you need to do the following command.
kubectl apply --filename service.yaml
Verify the domain URL for the service. It should be helloworld-go.default.example.com
.
kubectl get kservice helloworld-go \
--namespace default \
--output=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain
And call the service. Note: the curl --connect-to
option is only required when calling locally against minikube as
that option will add the correct host and sni headers to the request, and send the request to the host and port pair
returned from glooctl proxy address
.
curl --connect-to helloworld-go.default.example.com:80:$(glooctl proxy address --name clusteringress-proxy) http://helloworld-go.default.example.com
To clean up, delete the resources.
kubectl delete --filename service.yaml
Build locally, and deploy using Knative Serving
Run docker build
with your Docker Hub username.
docker build -t ${DOCKER_USERNAME}/helloworld-go .
docker push ${DOCKER_USERNAME}/helloworld-go
Deploy the service. Again, make sure you updated username in service.yaml
file, i.e., replace image reference
docker.io/scottcranton/helloworld-go
with your Docker Hub username.
kubectl apply --filename service.yaml
Verify domain URL for service. Should be helloworld-go.default.example.com
.
kubectl get kservice helloworld-go \
--namespace default \
--output=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain
And test your service.
curl --connect-to helloworld-go.default.example.com:80:$(glooctl proxy address --name clusteringress-proxy) http://helloworld-go.default.example.com
To clean up, delete the resources.
kubectl delete --filename service.yaml
Build using Knative Build, and deploy using Knative Serving
To install Knative Build, do the following. I’m using the kaniko
build template, so you’ll also need to install that
as well.
kubectl apply \
--filename https://github.com/knative/build/releases/download/v0.4.0/build.yaml
kubectl apply \
--filename https://raw.githubusercontent.com/knative/build-templates/master/kaniko/kaniko.yaml
To verify the Knative Build install, do the following.
kubectl get pods --namespace knative-build
I’d encourage forking my example GitHub repository https://github.com/scranton/helloworld-knative, so you can push code changes and see them in your environment.
Create a Kubernetes secret for your Docker Hub account that will allow Knative build to push your image. You also need to annotate the secret to indicate it’s for Docker. More details in Guiding credential selection.
kubectl create secret generic basic-user-pass \
--type="kubernetes.io/basic-auth" \
--from-literal=username=${DOCKER_USERNAME} \
--from-literal=password=${DOCKER_PASSWORD}
kubectl annotate secret basic-user-pass \
build.knative.dev/docker-0=https://index.docker.io/v1/
It should result in a secret like the following.
kubectl describe secret basic-user-pass
Name: basic-user-pass
Namespace: default
Labels: <none>
Annotations: build.knative.dev/docker-0: https://index.docker.io/v1/
Type: kubernetes.io/basic-auth
Data
====
username: 12 bytes
password: 24 bytes
Verify that serviceaccount.yaml
references your secret.
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-bot
secrets:
- name: basic-user-pass
Update service-build.yaml
with your GitHub and Docker usernames. This manifest will use Knative Build to create an
image using the kaniko-build
build template and deploy the service using Knative Serving with Gloo.
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: helloworld-go
namespace: default
spec:
runLatest:
configuration:
build:
apiVersion: build.knative.dev/v1alpha1
kind: Build
metadata:
name: kaniko-build
spec:
serviceAccountName: build-bot
source:
git:
url: https://github.com/{ GitHub username }/helloworld-knative
revision: master
template:
name: kaniko
arguments:
- name: IMAGE
value: docker.io/{ Docker Hub username }/helloworld-go
timeout: 10m
revisionTemplate:
spec:
container:
image: docker.io/{ Docker Hub username }/helloworld-go
imagePullPolicy: Always
env:
- name: TARGET
value: "Go Sample v1"
To deploy, apply the manifests.
kubectl apply \
--filename serviceaccount.yaml \
--filename service-build.yaml
Then you can watch the build and deployment happening.
kubectl get pods --watch
Once you see all the helloworld-go-0000x-deployment-....
pods are ready, then you can Ctrl+C to escape the watch, and
then test your deployment.
Verify the domain URL for service. Should be helloworld-go.default.example.com
.
kubectl get kservice helloworld-go \
--namespace default \
--output=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain
And test your service.
curl --connect-to helloworld-go.default.example.com:80:$(glooctl proxy address --name clusteringress-proxy) http://helloworld-go.default.example.com
Cleanup
kubectl delete \
--filename serviceaccount.yaml \
--filename service-build.yaml
kubectl delete secret basic-user-pass
Summary
Hopefully, this post gave you a taste for how Gloo and Knative can work together to provide you with a way to build and deploy your services on demand into Kubernetes.