1. Installation
Cert-Manager: version 1.3 이하만 됩니다. 체크 필요! (나중에 에러남)
Istio 따로 설치 하지 말고, 여기 있는 문서에서 Knative 먼저 설치후 추가로 Networking Layer 설정시에 Istio 설정함
1.1 Check Version
# Knavtive Server 버젼 확인
$ kubectl get namespace knative-serving -o 'go-template={{index .metadata.labels "serving.knative.dev/release"}}'
v0.11.2
# Knative Eventing 버젼 확인
$ kubectl get namespace knative-eventing -o 'go-template={{index .metadata.labels "eventing.knative.dev/release"}}'
1.2 Install Knative CLI
kn 명령을 내릴수 있는 클라이언트를 먼저 설치 합니다.
$ wget https://storage.googleapis.com/knative-nightly/client/latest/kn-linux-amd64
$ chmod 110 kn-linux-amd64
$ sudo mv kn-linux-amd64 /usr/local/bin/kn
1.3 Delete Existing Serving Component
강제로 업그레이드시 apply를 delete로 변경하고 이후 apply진행합니다. (서비스 안하고 있다는 전제)
일단 삭제이유는 kubeflow로 설치이후 버젼 업그레이드가 목적입니다.
귀찮아서 업그레이드 방식 따르지 않고 그냥 다 삭제해버리고 다시 깔아버리는 방법입니다.
바로 아래 코드는 서비스를 안하고 있을경우 강제로 업그레이드 하기 위해서 먼저 삭제부터 하는 코드 입니다.
주의하세요!!
$ kubectl get namespaces knative-serving -o json | jq '.spec.finalizers' = null | kubectl apply -f -
$ kubectl delete -f https://storage.googleapis.com/knative-nightly/serving/latest/serving-core.yaml
$ kubectl delete -f https://storage.googleapis.com/knative-nightly/serving/latest/serving-crds.yaml
$ kubectl delete -f https://github.com/knative/operator/releases/download/knative-v1.1.0/operator.yaml
$ kubectl get namespaces knative-serving
NAME STATUS AGE
knative-serving Terminating 44m
위를 확인해보면 Terminating에서 멈춰서 더이상 진행이 되지 않습니다.
Finelizer 부분을 설정해줘야 합니다.
참고로 그냥 edit으로 안됩니다.
$ kubectl get namespaces knative-serving -o json > knative-serving.json
$ vi knative-serving.json
안에 보면 finalizers 라고 있을겁니다.
" spec" : {
" finalizers" : [
" kubernetes"
]
}
finalizers 부분을 삭제하고 저장합니다.
" spec" : {
" finalizers" : [
]
}
주소를 알아내고, 편집한 json 파일로 대체를 합니다.
이때 알아낸 selfLink의 주소 뒤에 /finalize
를 붙여줘야 합니다.
$ kubectl get namespace knative-serving -o json | jq .metadata.selfLink
"/api/v1/namespaces/knative-serving"
$ kubectl replace --raw "/api/v1/namespaces/knative-serving/finalize" -f ./knative-serving.json
이후 kubectl get namespaces
로 확인해보면 삭제되어 있을겁니다.
1.4 Install Serving Component
Serving을 설치합니다.
$ kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.1.0/serving-crds.yaml
$ kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.1.0/serving-core.yaml
Knative Component를 설치합니다.
자세한 설치방법은 링크 를 참조 합니다.
Knative Operator 는 default namespace에 설치가 되야 합니다.
$ kubectl config set-context --current --namespace = default
$ kubectl apply -f https://github.com/knative/operator/releases/download/knative-v1.1.0/operator.yaml
$ kubectl get deployment knative-operator
NAME READY UP-TO-DATE AVAILABLE AGE
knative-operator 1/1 1 1 20s
1.5 Install Istio
반드시 아래에 있는 방법으로 설치를 해야지 Knative가 정상 작동합니다.
따로 Istio에 있는 문서대로 하면 설치가 안됩니다.
$ kubectl apply -l knative.dev/crd-install= true -f https://github.com/knative/net-istio/releases/download/knative-v1.1.0/istio.yaml
$ kubectl apply -f https://github.com/knative/net-istio/releases/download/knative-v1.1.0/istio.yaml
$ kubectl apply -f https://github.com/knative/net-istio/releases/download/knative-v1.1.0/net-istio.yaml
# 확인
$ kubectl --namespace istio-system get service istio-ingressgateway
1.5 cluster-local-gateway 설정
자세한 설치방법은 링크 를 참조 합니다.
cat << EOF > ./istio-minimal-operator.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
values:
global:
proxy:
autoInject: disabled
useMCP: false
# The third-party-jwt is not enabled on all k8s.
# See: https://istio.io/docs/ops/best-practices/security/#configure-third-party-service-account-tokens
jwtPolicy: first-party-jwt
addonComponents:
pilot:
enabled: true
prometheus:
enabled: false
components:
ingressGateways:
- name: istio-ingressgateway
enabled: true
- name: cluster-local-gateway
enabled: true
label:
istio: cluster-local-gateway
app: cluster-local-gateway
k8s:
service:
type: ClusterIP
ports:
- port: 15020
name: status-port
- port: 80
targetPort: 8080
name: http2
- port: 443
targetPort: 8443
name: https
EOF
실행
$ istioctl install -f istio-minimal-operator.yaml
This will install the Istio 1.11.0 default profile with [ "Istio core" "Istiod" "Ingress gateways" ] components into the cluster. Proceed? ( y/N) y
✔ Istio core installed
✔ Istiod installed
✔ Ingress gateways installed
✔ Installation complete
Thank you for installing Istio 1.11.
# 설치 확인
$ kubectl get pods --namespace istio-system
NAME READY STATUS RESTARTS AGE
cluster-local-gateway-c9d6b9dbf-2tqh5 1/1 Running 0 5m55s
istio-ingressgateway-754f55757d-sqgrk 1/1 Running 0 5m55s
istiod-59b95457f9-x5fcc 1/1 Running 0 8m19s
$ kubectl get svc -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT( S) AGE
cluster-local-gateway ClusterIP 172.20.87.103 <none> 15020/TCP,80/TCP,443/TCP 6m31s
istio-ingressgateway LoadBalancer 172.20.107.71 a1234567890abcdefghijklmnopqrstu-123456789.ap-northeast-2.elb.amazonaws.com 15021:31476/TCP,80:30369/TCP,443:31261/TCP 62m
istiod ClusterIP 172.20.138.114 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 62m
knative-local-gateway ClusterIP 172.20.106.201 <none> 80/TCP 15m
1.6 Install Eventing Component
KServing 설치시 필요없는 component
Custom Resource Definitions (CRD) 그리고 핵심 core components를 설치 합니다.
$ kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v1.1.0/eventing-crds.yaml
$ kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v1.1.0/eventing-core.yaml
모두 정상 작동 하는지 확인
$ kubectl get pods -n knative-eventing
NAME READY STATUS RESTARTS AGE
eventing-controller-56ccd89cd8-xxn9c 1/1 Running 0 39s
eventing-webhook-76b66cd56c-vrpzc 1/1 Running 0 38s
Broker Layer는 Apache Kafka, MT-Channel-based, RabbitMQ 등을 지원하고 있습니다.
MT Broker는 다음과 같이 설치 합니다.
자세한 내용은 링크 를 확인합니다.
$ kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v1.1.0/mt-channel-broker.yaml
2. Configuration
2.1 Custom Domain Setup
Knative Serving Route는 기본값으로 example.com 을 기본 도메인으로 사용합니다.
이후 KFServing을 할때도 모두 example.com 으로 나오기 때문에 이 부분의 변경이 반드시 필요 합니다.
$ kubectl edit cm config-domain --namespace knative-serving
처음 열면 아래와 같은 형식으로 생겼는데..
example:_| 로 시작하는 부분을 모두 삭제 합니다.
example.com 까지 모두 삭제 했으면, example.com 도메인을 변경합니다.
apiVersion : v1
data :
_example : |
################################
# #
# EXAMPLE CONFIGURATION #
# #
################################
# ...
example.com: |
kind : ConfigMap
변경이후 다음과 같습니다.
apiVersion : v1
data :
example.org : |
selector:
app: nonprofit
ml.incredible.ai : " "
svc.cluster.local : |
selector:
app: cluster-local
3. Getting Started
3.1 Hello World in Python
Python App
cat << EOF > app . py
import os
from flask import Flask
app = Flask ( __name__ )
@ app . route ( '/' )
def hello_world ():
target = os . environ . get ( 'TARGET' , 'World' )
return 'Hello {}! \n ' . format ( target )
if __name__ == "__main__" :
app . run ( debug = True , host = '0.0.0.0' , port = 8080 )
EOF
Dockerfile & Build
cat <<EOF > Dockerfile
FROM python:3.7-slim
ENV PYTHONUNBUFFERED=True
ENV APP_HOME=/app
WORKDIR \$APP=HOME
COPY . ./
RUN pip install Flask gunicorn
CMD exec gunicorn --bind :\$PORT --workers 1 --threads 8 --timeout 0 app:app
EOF
$ docker login
$ docker build -t andersonjo/knative-hello-world .
$ docker push andersonjo/knative-hello-world
Service & Deploy
andersonjo 부분을 Docker Hub 아이디로 변경 필요
cat <<EOF > service.yaml
apiVersion : serving.knative.dev/v1
kind : Service
metadata :
name : helloworld-python
namespace : knative-samples
spec :
template :
spec :
containers :
- name : helloworld-python
image : docker.io/andersonjo/knative-hello-world
imagePullPolicy : IfNotPresent
env :
- name : TARGET
value : " Python Sample v1"
EOF
$ kubectl apply -f service.yaml
$ kubectl get ksvc helloworld-python -n knative-samples
NAME URL LATESTCREATED LATESTREADY READY REASON
helloworld-python http://helloworld-python.default.ai.platform helloworld-python-69cbt helloworld-python-69cbt True
$ INGRESS_HOST = $( kubectl -n istio-system get service istio-ingressgateway -o jsonpath = '{.status.loadBalancer.ingress[0].hostname}' )
$ curl -H "Host:helloworld-python.default.ai.platform" $INGRESS_HOST
$ curl -H "Host:helloworld-python.default.ml.inthewear.com" $INGRESS_HOST
Hello Python Sample v1!
3. Autoscale
3.1 Autoscaler Types
Knative Pod Autoscaler (KPA)
Knative Serving Core의 한 부분이며, 디폴트값이 사용이다.
트래픽이 없을경우 0으로 scale 하는 기능도 있음 (scale down)
CPU 기반의 autoscaling은 지원하지 않음
Horizontal Pod Autoscaler (HPA)
Knative Serving Core에서 제공되는 기능이 아니며, Knative Serving 설치이후 따로 설정해줘야 함
트래픽이 없을 경우 0으로 scale down하는 기능이 없음
CPU 기반의 autoscaling 제공
설정은 class
annotation을 설정해서 타입을 설정 할 수 있습니다.
Global Settings Key : pod-autoscaler-class
Per-revision annotation key : autoscaling.knative.dev/class
Possible values : kpa.autoscaling.knative.dev
or hpa.autoscaling.knative.dev
Default : kpa.autoscaling.knative.dev
3.2 Configuration
3.2.1 Per Revision Example
spec.template.metadata.annotations 여기에서 autoscaling.knative.dev/class
설정
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go
namespace: default
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/class: "kpa.autoscaling.knative.dev"
spec:
containers:
- image: gcr.io/knative-samples/helloworld-go
3.2.2 Global(ConfigMap)
$ kubectl edit configmap config-autoscaler -n knative-serving
apiVersion : v1
kind : ConfigMap
metadata :
name : config-autoscaler
namespace : knative-serving
data :
pod-autoscaler-class : " kpa.autoscaling.knative.dev"
3.2.3 Global(Operator)
$ kubectl edit configmap config-autoscaler -n knative-serving
apiVersion : operator.knative.dev/v1alpha1
kind : KnativeServing
metadata :
name : knative-serving
spec :
config :
autoscaler :
pod-autoscaler-class : " kpa.autoscaling.knative.dev"
3.3 Example
cat <<EOF > service.yaml
apiVersion : serving.knative.dev/v1
kind : Service
metadata :
name : autoscale-go
namespace : default
spec :
template :
metadata :
annotations :
# Target 10 in-flight-requests per pod.
autoscaling.knative.dev/target : " 10"
spec :
containers :
- image : gcr.io/knative-samples/autoscale-go:0.1
EOF
$ kubectl apply -f service.yaml
$ kubectl get ksvc autoscale-go
NAME URL LATESTCREATED LATESTREADY READY REASON
autoscale-go http://autoscale-go.default.ai.platform autoscale-go-xdstf autoscale-go-xdstf True
$ INGRESS_HOST = $( kubectl -n istio-system get service istio-ingressgateway -o jsonpath = '{.status.loadBalancer.ingress[0].hostname}' )
$ curl -H "Host:autoscale-go.default.ai.platform" " ${ INGRESS_HOST } ?sleep=500&prime=10000&bloat=5"
Allocated 5 Mb of memory.
The largest prime less than 10000 is 9973.
Slept for 500.11 milliseconds.
Load Test를 진행합니다.
$ hey -z 30s -c 200 -H "Host: autoscale-go.default.ai.platform" "http:// ${ INGRESS_HOST } ?sleep=5000&prime=1000000&bloat=20"
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
autoscale-go-2fkh2-deployment-65bc9d7764-zq2sr 2/2 Running 0 5m17s
autoscale-go-5n6gm-deployment-657678f8bd-xp87n 2/2 Running 0 6m31s
autoscale-go-dm54z-deployment-c48fcb7ff-49ckr 2/2 Running 0 179m