kubernetes

istio 배포

misankim 2023. 3. 8. 23:33

istio 배포


공식 가이드


# 설치

## istioctl 로 설치


curl -L https://istio.io/downloadIstio | sh -
cd istio-*
export PATH=$PWD/bin:$PATH

istioctl install --set profile=demo -y

배포된 istio 관련 리소스 확인
kubectl get all -n istio-system

설치된 istio profile 확인

istioctl profile dump

앱 배포 시 envoy 사이드카 프록시를 자동으로 삽입하도록 앱을 배포할 네임스페이스에 레이블을 추가
-> envoy 사이드카 프록시가 정상적으로 배포되었다면 파드에 포함된 컨테이너가 1개(READY 1/1)가 아닌 2개(READY 2/2)로 보이는 것이 정상

kubectl label namespace default istio-injection=enabled
kubectl get ns --show-labels

(참고) istio 관련 리소스

❯ kubectl get all -n istio-system
NAME                                        READY   STATUS    RESTARTS   AGE
pod/istio-egressgateway-66fdd867f4-nhmmc    1/1     Running   0          3m53s
pod/istio-ingressgateway-77968dbd74-2sb8m   1/1     Running   0          3m53s
pod/istiod-699b647f8b-2zcnk                 1/1     Running   0          4m9s

NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                                                      AGE
service/istio-egressgateway    ClusterIP      100.66.9.189   <none>        80/TCP,443/TCP                                                               3m52s
service/istio-ingressgateway   LoadBalancer   100.66.3.174   34.64.56.24   15021:32719/TCP,80:32147/TCP,443:32119/TCP,31400:31958/TCP,15443:31065/TCP   3m52s
service/istiod                 ClusterIP      100.66.3.216   <none>        15010/TCP,15012/TCP,443/TCP,15014/TCP                                        4m9s

NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/istio-egressgateway    1/1     1            1           3m54s
deployment.apps/istio-ingressgateway   1/1     1            1           3m54s
deployment.apps/istiod                 1/1     1            1           4m10s

NAME                                              DESIRED   CURRENT   READY   AGE
replicaset.apps/istio-egressgateway-66fdd867f4    1         1         1       3m54s
replicaset.apps/istio-ingressgateway-77968dbd74   1         1         1       3m54s
replicaset.apps/istiod-699b647f8b                 1         1         1       4m10s

## istio operator 로 설치


IstioOperator 옵션 참고


istioctl operator init
-> istio-operator 네임스페이스에 istio-operator 관련 리소스가 생성됨
-> IstioOperator 리소스 작성하면 자동으로 istio 배포
-> istio 초기 배포 이후 IstioOperator 가 변경되면 변경되는 내용을 istio operator 가 실시간으로 istio 에 반영해줌

kubectl apply -f - <<EOF
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  namespace: istio-system
  name: istiocontrolplane
spec:
  profile: demo
  meshConfig:
    accessLogFile: /dev/stdout
  values:
    pilot:
      enabled: true
      autoscaleEnabled: true
      autoscaleMin: 1
      autoscaleMax: 5
      resources:
        requests:
          cpu: 500m
          memory: 2048Mi
        limits:
          cpu: 500m
          memory: 2048Mi
    gateways:
      istio-ingressgateway:
        autoscaleEnabled: true
        type: ClusterIP
        serviceAnnotations:
          cloud.google.com/backend-config: '{"default": "istio-ingressgateway"}'
      istio-egressgateway:
        autoscaleEnabled: true
EOF

kubectl get IstioOperator -n istio-system
 
## istio operator 로 설치한 istio, operator 제거

kubectl delete istiooperators.install.istio.io -n istio-system istiocontrolplane

istioctl uninstall -y --purge

kubectl delete ns istio-system istio-operator --grace-period=0 --force


# 샘플 앱 배포

kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

kubectl get all

배포된 앱 정상 작동 확인
kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"


# 외부로 앱 노출

kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml

구성 검증
istioctl analyze

로드밸런서 지원 여부 확인(EXTERNAL-IP)
kubectl get svc istio-ingressgateway -n istio-system

환경 변수 설정(복잡)
export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT

환경 변수 설정(간단)
export GATEWAY_URL=$(kubectl get svc istio-ingressgateway -n istio-system -o json | jq -r .status.loadBalancer.ingress[0].ip)

확인
echo "$GATEWAY_URL"

접속할 외부 주소
echo "http://${GATEWAY_URL}/productpage"


# 애드온 설치 및 접속

애드온 설치
kubectl apply -f samples/addons

prometheus 접속을 위한 포트포워드
kubectl -n istio-system port-forward \
  $(kubectl -n istio-system get pod -l app=prometheus -o jsonpath='{.items[0].metadata.name}') 9090:9090

grafana 접속을 위한 포트포워드
kubectl -n istio-system port-forward \
    $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') 3000:3000

jaeger 접속을 위한 포트포워드
kubectl -n istio-system port-forward \
    $(kubectl -n istio-system get pod -l app=jaeger -o jsonpath='{.items[0].metadata.name}') 20001:16686


# kiali 대시보드 배포

kiali 배포
kubectl rollout status deployment/kiali -n istio-system

대시보드 프록시 실행(자동으로 브라우저로 연결됨)
istioctl dashboard kiali

혹은 포트포워드
kubectl -n istio-system port-forward \
$(kubectl -n istio-system get pod -l app=kiali -o jsonpath='{.items[0].metadata.name}') 20001:20001

좌측 메뉴에서 그래프 선택 후 네임스페이스 default 선택

샘플 데이터 생성
for i in $(seq 1 100); do curl -s -o /dev/null "http://$GATEWAY_URL/productpage"; done

샘플 데이터 생성 후 대시보드의 그래프가 정상적으로 보여지는지 확인

(참고) 애드온으로 배포된 prometheus 가 수집하는 메트릭

istio-telemetry.istio-system:42422: The istio-mesh job returns all Mixer-generated metrics.

istio-telemetry.istio-system:15014: The istio-telemetry job returns all Mixer-specific metrics. Use this endpoint to monitor Mixer itself.

istio-proxy:15090: The envoy-stats job returns raw stats generated by Envoy. Prometheus is configured to look for pods with the envoy-prom endpoint exposed. The add-on configuration filters out a large number of envoy metrics during collection in an attempt to limit the scale of data by the add-on processes.

istio-pilot.istio-system:15014: The pilot job returns the Pilot-generated metrics.

istio-galley.istio-system:15014: The galley job returns the Galley-generated metrics.

istio-policy.istio-system:15014: The istio-policy job returns all policy-related metrics.

istio-citadel.istio-system:15014: The istio-citadel job returns all Citadel-generated metrics.


# 제거

kubectl delete -f samples/addons
istioctl manifest generate --set profile=demo | kubectl delete --ignore-not-found=true -f -
istioctl tag remove default

kubectl delete namespace istio-system

kubectl label namespace default istio-injection-


(참고) nginx 로 리버스 프록시 파드 사용 시 404 에러가 찍히는 경우
-> envoy 프록시는 호스트 헤더와 경로를 기반으로 프록시할 대상을 인식하는데 nginx 설정에 의해 호스트 헤더가 덮어 씌어지면 envoy 에서 경로를 찾지 못해 404 에러 발생
-> nginx 의 default.conf 파일에 아래 옵션이 있다면 주석


proxy_set_header Host                    $host;


(참고) nginx 로 리버스 프록시 파드 사용 시 426 에러가 찍히는 경우


nginx 의 default.conf 파일에 아래 옵션 추가

proxy_http_version 1.1;


# gateway 에 ssl 인증서 적용


openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./my-flask-app.example.com.key -out ./my-flask-app.example.com.crt -subj "/CN=my-flask-app.example.com/O=my-flask-app.example.com"

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./keycloak.example.com.key -out ./keycloak.example.com.crt -subj "/CN=keycloak.example.com/O=keycloak.example.com"

kubectl create -n istio-system secret tls my-flask-app-credential --key=my-flask-app.example.com.key --cert=my-flask-app.example.com.crt

kubectl create -n istio-system secret tls keycloak-credential --key=keycloak.example.com.key --cert=keycloak.example.com.crt


cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: istio-ingressgateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
  - port:
      number: 443
      name: https-my-flask-app
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: my-flask-app-credential
    hosts:
    - my-flask-app.example.com
  - port:
      number: 443
      name: https-keycloak
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: keycloak-credential
    hosts:
    - keycloak.example.com
EOF


# 사이드카 프록시를 주입하지 않도록 label 추가


❯ cat rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: my-flask-app
spec:
...
  template:
    metadata:
      labels:
        app: my-flask-app
        sidecar.istio.io/inject: "false"
    spec:
      terminationGracePeriodSeconds: 30
      serviceAccount: pubsub-ksa
      containers:
...


# istio 업그레이드


설치 전 체크
istioctl x precheck

업그레이드
istioctl upgrade

버전 확인
istioctl version

프로파일 설정값 확인
istioctl profile dump


# static 응답(403, 404 등) 반환
-> directResponse 설정은 istio 버전 1.15 이상에서만 사용 가능


apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: ratings-route
spec:
  hosts:
  - ratings.prod.svc.cluster.local
  http:
  - match:
    - uri:
        exact: /v1/getProductRatings
    directResponse:
      status: 503
      body:
        string: "unknown error"
  ...


# sticky session 설정


apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: dr-my-flask-app
spec:
  host: svc-my-flask-app.my-flask-app.svc.cluster.local
  subsets:
  - name: canary
    labels:
      app: my-flask-app
  - name: stable
    labels:
      app: my-flask-app
  trafficPolicy:
    loadBalancer:
      consistentHash:
        httpCookie:
          name: istio-session
          ttl: 0s