Introduction: Microservices and containerization have brought about the need to decompose applications into small reusable units, which are usually run as separate processes or in separate containers. The Pod model of Kubernetes allows users to create a deployment unit that can package multiple containers as a single instance of an application. Knative users currently also have demands for deploying multiple containers into one Pod. The ability to support multiple containers will facilitate the deployment of a wider range of workloads into the Knative Serving model. Therefore, Knative has provided multiple container capabilities starting from version 0.16.0.
Guide
Microservices and containerization have brought demands to decompose applications into small reusable units, which are usually run as separate processes or in separate containers. The Pod model of Kubernetes allows users to create a deployment unit that can package multiple containers as a single instance of an application.
Knative users currently also have demands for deploying multiple containers into one Pod. The ability to support multiple containers will facilitate the deployment of a wider range of workloads into the Knative Serving model. Therefore, Knative has provided multiple container capabilities starting from version 0.16.0.
Multi-container support
Single container introduction
Versions before Knative 0.16.0 only support the setting of one business container, that is, only one container can be set in Knative Service. In the process of service creation, a QUEUE container will be added to the POD by default. The main user of this container takes over the ingress traffic and is used for traffic-based KPA indicator collection. A typical Knative Service is as follows:
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go
spec:
template:
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/knative-sample/helloworld-go:73fbdd56
env:
- name: TARGET
value: "Knative"
The schematic diagram of the POD in operation after creation is as follows:
If we want to add a custom SideCar container (usually used for network interoperability, file downloading and copying and other auxiliary functions), there is no way to support it, which limits the actual usage scenarios.
Multi-container introduction
Knative has also supported multi-containers since version 0.16.0 (nothing to say, the natural features of k8s pod must be supported)
So how to use multiple containers? It's very simple. In fact, you can configure multiple in the containers attribute. The example is as follows:
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: multi-container
namespace: default
spec:
template:
spec:
containers:
- image: docker.io/savita3020/servingcontainer
ports:
- containerPort: 8881
- image: docker.io/savita3020/sidecarcontainer
Turn on the multi-container feature
- Alibaba Cloud Knative v0.18.3 has been enabled by default.
- Community Knative 0.16.0 is not enabled by default. Starting from 0.17.0, it is enabled by default. Perform the following operations to check whether it is enabled:
$ kubectl -n knative-serving get configmap config-features -oyaml
......
multi-container: "enabled"
......
Multi-container practice
Prerequisites
Create service
Next we create a multi-container service, which includes two containers:
- servingcontainer 容器
- sidecarcontainer 容器
The servingcontainer calls sidecarcontainer, the sample code is as follows:
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
log.Println("serving container received a request.")
res, err := http.Get("http://127.0.0.1:8882")
if err != nil {
log.Fatal(err)
}
resp, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Fatal(err)
}
fmt.Fprintln(w, string(resp))
}
func main() {
log.Print("serving container started...")
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8881", nil))
}
The sidecarcontainer container is used to print the information "Yay!! multi-container works", the sample code is as follows:
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
log.Println("sidecar container received a request.")
fmt.Fprintln(w, "Yay!! multi-container works")
}
func main() {
log.Print("sidecar container started...")
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8882", nil))
}
We create a multi-container service
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: multi-container
namespace: default
spec:
template:
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/knative-sample/servingcontainer:v1
ports:
- containerPort: 8881
- image: registry.cn-hangzhou.aliyuncs.com/knative-sample/sidecarcontainer:v1
Execute the deployment command:
kubectl apply -f multi-container.yaml
Check the pod information and find a three containers (queue container, servingcontainer container, sidecarcontainer container):
richard@B-N3TEMD6P-1650 multi-container % kubectl get po
NAME READY STATUS RESTARTS AGE
multi-container-dfqtv-deployment-799c4f694c-bkc8t 3/3 Running 0 9s
Access service:
richard@B-N3TEMD6P-1650 multi-container % curl -H "host: multi-container.default.example.com" http://182.92.208.172
Yay!! multi-container works
We can see that multi-container access has taken effect.