반응형

Argo Rollout 은 new version pods 와 old version pods 를 어떻게 구분하는 것일까? Rollout 리소스로 생성하면 ReplicaSet 의 형태인 Pod 템플릿 영역인 (spec.template) 과 동일하다. 즉 ReplicaSet 이 Selector 로 지정한 label 로 Pod 를 찾아가는 것이다.

아래 Rollout 1개와 Service 2개를 가지는 sample yaml 파일을 배포하여 동작 방법을 살펴보자.

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollout-bluegreen
spec:
  replicas: 2
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: rollout-bluegreen
  template:
    metadata:
      labels:
        app: rollout-bluegreen
    spec:
      containers:
      - name: rollouts-demo
        image: argoproj/rollouts-demo:blue
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
  strategy:
    blueGreen:
      activeService: rollout-bluegreen-active
      previewService: rollout-bluegreen-preview
      autoPromotionEnabled: false

---
kind: Service
apiVersion: v1
metadata:
  name: rollout-bluegreen-active
spec:
  selector:
    app: rollout-bluegreen
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

---
kind: Service
apiVersion: v1
metadata:
  name: rollout-bluegreen-preview
spec:
  selector:
    app: rollout-bluegreen
  ports:
  - protocol: TCP
    port: 80

Rollout 은 strategy 만 제외하면 ReplicaSet 혹은 Deployment 와 동일하다. 그래서 Rollout 을 배포하면 ReplicaSet 과 Pod 는 Kubernetes Core Resource 타입으로 동일하게 생성되고 조회할 수 있다.

 

.spec.selector.matchLabels 와 .spec.template.metadata.labels 에서 지정한 label 은 동일해야 한다. 이 부분은 ReplicaSet 에서 요구하는 spec 과 같다.

 

strategy 의 blueGreen 에는 rollout-bluegreen-active 와 rollout-bluegreen-preview 라는 service 가 2개가 지정되어 있다. Service 는 DNS 명 처럼 이름으로 IP 를 매칭하는 값을 가지는 기능과 Pod 를 연결하여 load balancing 해주는 대표적인 기능이 있다. rollout-bluegreen-active Service 에는 selector 로 "app: rollout-bluegreen" 값이 지정되어 있는데 이는 Rollout Template 에서 지정된 Pod 의 labels 를 가리킨다.

 

그런데 rollout-bluegreen-active Service 와 rollout-bluegreen-preview 2개 모두 같은 selector 로 같은 Pod 를 보고 있는데 어떻게 new version 과 old version 을 구분할까?

 

배포한 후에 설정들이 어떻게 바뀌는지 살펴보자.

$ kubectl apply -f rollout-blue-green.yaml
$ kubectl argo rollouts get rollout rollout-bluegreen --watch

 

 

rollout 명이 rollout-bluegreen-[해시코드값] 으로 되어 있는데 여기서 해시코드 값이 6565b74f44 은 ReplicaSet 의 해시코드와 동일하다.

$ kubectl get rs rollout-bluegreen

 

 

이 해시코드 값은 Service 에서도 찾아 볼 수 있다.

$ kubectl get svc rollout-bluegreen-active -o yaml
...
apiVersion: v1
kind: Service
metadata:
  name: rollout-bluegreen-active
  namespace: default
spec:
  clusterIP: 10.233.59.133
  clusterIPs:
  - 10.233.59.133
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: rollout-bluegreen
    rollouts-pod-template-hash: 6565b74f44
  sessionAffinity: None
  type: ClusterIP
...

selector 의 label 에 자동으로 rollouts-pod-template-hash: 6565b74f44 이 추가되어 rollout-bluegreen-active Service 는 현재 version 의 rollout 으로 생성된 Pod 를 가리키는 것을 알 수 있다.

이제 이미지를 업데이트 하여 upgrade 배포를 해보자.

$ kubectl argo rollouts set image rollout-bluegreen rollouts-demo=argoproj/rollouts-demo:yellow
$ kubectl argo rollouts get rollout rollout-bluegreen --watch

 

 

revision:2 아래에 rollout-bluegreen-6b5dc99488 이라는 새로운 해시코드 값으로 ReplicaSet 이 생성되었다.

rollout-bluegreen-preview Service 의 selector 로 지정된 labels 을 보면 rollouts-pod-template-hash:6b5dc99488 가 생성되어 new version 의 pod 를 가리키는 것을 알 수 있다.

$ kubectl get svc rollout-bluegreen-preview -o yaml
...
apiVersion: v1
kind: Service
metadata:
  name: rollout-bluegreen-preview
  namespace: default
spec:
  clusterIP: 10.233.44.227
  clusterIPs:
  - 10.233.44.227
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: rollout-bluegreen
    rollouts-pod-template-hash: 6b5dc99488
  sessionAffinity: None
  type: ClusterIP
...

배포를 완료하고 ReplicaSet 을 조회해 보면 이전 해시코드 값을 갖는 ReplicaSet 의 DESIRED, CURRENT, READY 가 0 으로 세팅되어 있는 것을 알 수 있다.

$ kubectl argo rollouts promote rollout-bluegreen
$ kubectl get rs -l app=rollout-bluegreen
NAME                           DESIRED   CURRENT   READY   AGE
rollout-bluegreen-6565b74f44   0         0         0       5h35m
rollout-bluegreen-6b5dc99488   2         2         2       10m

이 방식을 응용하면 Deployment 로도 쉽게 배포 전략을 활용할 수 있다.

반응형
Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

반응형

Argo rollout 은 Progressive Delivery 를 지원하는 툴이다.

아래의 그림에서 보듯이 Canary 배포를 진행할 때 일시적으로 배포를 홀딩한 상태에서 new version 에 대한 배포가 성공되었는지를 Metric 으로 판단하여 안전하게 배포를 완료할 수 있다. (metric 수집과 쿼리는 Prometheus 를 포함하여 다양한 모니터링 툴을 지원한다.)

 

 

Metric 을 통해 배포의 성공 여부를 판단하여 rollback 할 것인지, 계속 진행할 것인지를 결정할 수 있다는 것이 중요한 키 포인트다. 왜냐하면 쿠버네티스의 롤링 업데이트는 readiness 로 배포 성공여부를 판단하는데 이는 Metric 보다 판단하기에 부족할 수 있고, 중간에 에러가 발생하면 멈출 수 는 있지만 자동으로 rollback 되지는 않기 때문이다. 

Argo Quick 설치하기

# kubectl create namespace argo-rollouts
# kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

 

kubectl plugin 설치하기

# curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
# chmod +x ./kubectl-argo-rollouts-linux-amd64
# mv ./kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts
# kubectl argo rollouts version

 

 

Basic rollout 설치하기

# cd ~/argo-rollout-demo
# curl -Lo basic-rollout-blue.yaml https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/basic/rollout.yaml
# curl -Lo basic-service.yaml https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/basic/service.yaml

# kubectl apply -f basic-rollout-blue.yaml
# kubectl apply -f basic-service.yaml

# kubectl patch svc rollouts-demo --patch \
'{"spec": { "type": "NodePort", "ports": [ { "nodePort": 31080, "port": 80, "protocol": "TCP", "targetPort": "http", "name": "http" } ] } }'

 

 

화면 접속

http://k2-master01:31080

콘솔 보기

# kubectl argo rollouts get rollout rollouts-demo --watch

 

Basic rollout Canary 업그레이드

# kubectl argo rollouts set image rollouts-demo rollouts-demo=argoproj/rollouts-demo:yellow

rollout 전략이 처음 step 은 20% 만 변경하는 것이기 때문에 5개의 replica 중에 1개만 old version(blue) 이고 4 개는 new version(yellow) 이다. 그리고 현재는 pause (일시멈춤) 상태로 더이상 rollout 배포가 진행되지 않고 있다.

 

 

Basic rollout Canary 업그레이드 계속 진행

# kubectl argo rollouts promote rollouts-demo

 

promote 로 계속 rollout 업그레이드를 진행하면 점차 new version 이 revision:2 영역인 canary 로 replica 개수를 증가시키는 것을 볼 수 있다. duration 을 10으로 주었기 때문에 10 초 단위로 20% 씩 자동으로 올려준다.

 

일정 시간이 다 지나면 전체가 전부 다 업그레이드 된다.

 

argo rollout 은 metric 으로 정의한 성공 여부에 따라 배포를 계속 진행할 것인지 아니면 abort 시킬 것인지를 자동으로 결정할 수 있다.

 

출처: https://argoproj.github.io/argo-rollouts

반응형
Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

반응형

Kubernetes 기반의 monitoring 을 구현한다면 최우선 순위로 검토되는 오픈소스는 단연 Prometheus 이다. 최근에는 Kubernetes 위에 실행되는 Pod와 같은 자원을 효과적으로 관리하기 위해서 Operator 를 활용하고 있는 추세인데 이에 맞춰 Prometheus 에서도 Operator 를 지원하고 있다. 일반적으로 Operator 는 중심이 되는 프로그램, Pod 와 같이 CustomResource를 정의하면 자동으로 해당 프로그램을 띄우는 방식으로 사용된다. 하지만 Prometheus Operator Prometheus 자체를 띄우고 관리하는 방식이 아니라 Prometheus 에서 사용되는 설정 등을 관리하기 위해서 사용된다. 한마디로 말하면 Prometheus OperatorPrometheus 를 모두 설치하고, Operator Prometheus 설정을 CustomResource 로 관리하는 방식이다.

 

그럼 이제 Prometheus Operator Prometheus 를 설치해 보자. 둘다 모두 prometheus-community 에서 제공하는 helm chart helm3 를 이용하여 설치한다.

 

helm repo 를 아래와 같이 등록한다.

$ helm repo add prometheus https://prometheus-community.github.io/helm-charts
$ helm repo update

$ helm search repo prometheus

 

많은 차트들이 검색되는데 그중에서 kube-prometheus-stack chart Prometheus Operator Prometheus 를 설치한다.

 

1. Prometheus Operator 설치

helm chart 에서 Oeveride value 를 아래와 같이 지정한다.

# vi prometheus-operator-values.yaml

namespaceOverride: prometheus
fullnameOverride: prometheus-operator
defaultRules:
  create: false
alertmanager:
  enabled: false
grafana:
  enabled: false
kubeApiServer:
  enabled: false
kubelet:
  enabled: false
kubeControllerManager:
  enabled: false
coreDns:
  enabled: false
kubeDns:
  enabled: false
kubeEtcd:
  enabled: false
kubeScheduler:
  enabled: false
kubeProxy:
  enabled: false
kubeStateMetrics:
  enabled: false
nodeExporter:
  enabled: false
prometheus:
  enabled: false
prometheusOperator:
  enabled: true
  resources:
    limits:
      cpu: 2
      memory: 2Gi
    requests:
      cpu: 1
      memory: 1Gi
  serviceMonitor:
    selfMonitor: false
  nodeSelector:
    monitoring: enabled
  createCustomResource: true
  cleanupCustomResource: true
  cleanupCustomResourceBeforeInstall: true

 

Prometheus Operator 를 설치할 namespacenamespaceOverride prometheus 로 지정한다.

Deployments 로 생성될 이름은 fullnameOverride prometheus-operator 로 지정한다.

Operator 만 명시적으로 생성할 의도로 나머지 prometheus, exporter, alertmanager 등은 enabled: false 로 지정하여 생성하지 않는다.

 

Prometheus Operator 가 생성될 노드를 nodeSelector 로 지정할 수 있으며 여기서는 monitoring: enabled 로 세팅했으므로 Kubernetes node 에 해당 label 이 설정된 노드가 있어야 한다.

 

$ kubectl create ns prometheus
$ kubectl label namespace prometheus name=prometheus

$ kubectl label node k1-node01 monitoring=enabled
$ kubectl label node k1-node02 monitoring =enabled
$ kubectl label node k1-node03 monitoring =enabled

$ kubectl create secret generic etcd-client-cert -n prometheus \
--from-file=etcd-ca=/etc/ssl/etcd/ssl/ca.pem \
--from-file=etcd-client=/etc/ssl/etcd/ssl/member-k1-master01.pem \
--from-file=etcd-client-key=/etc/ssl/etcd/ssl/member-k1-master01-key.pem

 

 

prometheus namespace labelname=prometheus 로 준 이유는 나중에 CustomeResource Service Monitor prometheus namespace 안에 생성되면 자동으로 해당 설정을 적용하기 위해서 Operator 에 알려주는 정보이다. 별도로 설정하지 않아도 prometheus namesapce 에는 자동으로 설정된다.

 

또 한가지 알아야 할 것은 etcd metric 을 가져오기 위해서는 endpoint 뿐만이 아니라 mTLS 인증서도 있어야 한다. kubernetes kubespary 로 설치하였다면 master 노드의 해당 위치에 etcd 인증서가 있으니 이를 가지고 secret 을 미리 생성해 놓아야 metric 을 가져올 수 있다.

 

이제 helm 명령어로 Prometheus Operator를 설치한다. upgrade -i 옵션을 주면 설치가 안되어 있을 경우에는 create 명령과 동일하고 설치가 되어 있을 경우에는 upgrade 명령과 동일하다.

 

$ helm upgrade -i prometheus-operator prometheus/kube-prometheus-stack --version 14.0.1 -f prometheus-operator-values.yaml -n prometheus

 

 

 

2. Prometheus 설치

 

동일한 kube-prometheus-stack 차트로 prometheus 를 설치한다.

 

# vi prometheus-values.yaml

defaultRules:
  create: false
alertmanager:
  enabled: true
  service:
    type: NodePort
    nodePort: 30903
  alertmanagerSpec:
    nodeSelector:
      monitoring: enabled
grafana:
  enabled: false
kubeApiServer:
  enabled: true
  serviceMonitor:
    namespaceSelector:
      matchNames:
      - default
kubeEtcd:
  enabled: true
  endpoints:
    - 192.168.30.13
    - 192.168.30.14
    - 192.168.30.15
  serviceMonitor:
    scheme: https
    insecureSkipVerify: false
    serverName: localhost
    caFile: /etc/prometheus/secrets/etcd-client-cert/etcd-ca
    certFile: /etc/prometheus/secrets/etcd-client-cert/etcd-client
    keyFile: /etc/prometheus/secrets/etcd-client-cert/etcd-client-key
kubeStateMetrics:
  enabled: false
nodeExporter:
  enabled: false
prometheusOperator:
  enabled: false
  serviceMonitor:
    selfMonitor: true
prometheus:
  enabled: true
  service:
    type: NodePort
    nodePort: 30008
  # Service for thanos service discovery on sidecar
  # Enable this can make Thanos Query can use
  # `--store=dnssrv+_grpc._tcp.${kube-prometheus-stack.fullname}-thanos-discovery.${namespace}.svc.cluster.local` to discovery
  # Thanos sidecar on prometheus nodes
  # (Please remember to change ${kube-prometheus-stack.fullname} and ${namespace}. Not just copy and paste!)
  thanosService:
    enabled: false
    annotations: {}
    labels: {}
    portName: grpc
    port: 10901
    targetPort: "grpc"
  thanosIngress:
    enabled: false
    type: NodePort
    nodePort: 30901
  prometheusSpec:
    externalLabels:
      cluster: k1
    nodeSelector:
      monitoring: enabled
    secrets:
      - etcd-client-cert
    ruleNamespaceSelector:
      matchLabels:
        name: prometheus
    ruleSelectorNilUsesHelmValues: false
    serviceMonitorNamespaceSelector:
      matchLabels:
        name: prometheus
    serviceMonitorSelectorNilUsesHelmValues: false
    podMonitorNamespaceSelector:
      matchLabels:
        name: prometheus
    podMonitorSelectorNilUsesHelmValues: false
    retention: 10d
    replicas: 1
    storageSpec:
      volumeClaimTemplate:
        spec:
          storageClassName: rbd
          accessModes: ["ReadWriteOnce"]
          resources:
            requests:
              storage: 100Gi
    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#thanosspec
    thanos:
      version: v0.18.0

 

 

kubeEtcd etcd master 3대에 설치되어 있어 endpoint에 해당 ip 를 모두 넣었으며 caFile, certFile, keyFile 은 앞서 설치한 secret 명을 경로로 포함하고 있다. alertmanager prometheus 모두 nodePort 로 설치하여 접근할 수 있다.

serviceMonitorNamespaceSelector podMonitorNamespaceSelector 를 지정하여 Monitor 할 대상을 CustomResource 를 통해 자동으로 설정할 수 있다. 앞서 prometheus namespace 를 생성할 때 label name=prometheus 로 지정한 이유가 바로 이 부분이다.

마지막으로 Prometheus 가 사용할 storage class rbd 로 지정하여 자동으로 생성되게 설정한다.

 

helm 으로 Prometheus 를 설치하는 명령은 다음과 같다.

 

$ helm upgrade -i prometheus prometheus/kube-prometheus-stack --version 14.0.1 -f prometheus-values.yaml -n prometheus

 

 

Prometheus 접속 url: http://<node-ip>:30008

 

 

alertmanager 접속 url: http://<node-ip>:30903

반응형
Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

반응형

KubeCon 에서 다른 건 몰라도 이 내용은 꼭 들어야 한다.

 

Kubernetes Cluster 에서 Networking 관점에서 문제가 생길 수 있는 부분들을 설명했다.

 

docs.cilium.io/en/v1.9/intro/#what-is-hubble

 

Introduction to Cilium & Hubble — Cilium 1.9.6 documentation

Protect and secure APIs transparently Ability to secure modern application protocols such as REST/HTTP, gRPC and Kafka. Traditional firewalls operates at Layer 3 and 4. A protocol running on a particular port is either completely trusted or blocked entirel

docs.cilium.io

editor.cilium.io/

 

Network Policy Editor for Kubernetes

editor.cilium.io makes it easy to build, visualize, and make sense of Network Policies, which can then be downloaded as YAML and run in any Kubernetes cluster with a Network Policy-aware CNI.

editor.cilium.io

20210506_2120_How to Break your Kubernetes Cluster with Networking - Thomas Graf, Isovalent.pdf
3.32MB

반응형
Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

반응형

Golang 으로 개발된 애플리케이션을 Docker image 로 만드는 Dockerfile 이다.

이미지 사이즈를 줄이기 위해서 빌드 이미지와 실행 이미지를 구분하여 작성하였다.

 

실행 이미지를 더 작게 만들고 싶으면 base를 golang 이미지 대신 alphine 이미지로 만들면 된다.

 

한가지 tip 이라 하면 RUN go mod vendor 를 먼저 하고 나중에 COPY . . 를 하여 소스를 복사한 부분이다.

만약 소스 복사를 먼저하면 변경되 소스로 인해서 (하위 layer 의 변경) go mod vendor 로 다운로드 하는 부분을 수행하게 된다. 하지만 go mod vendor 를 먼저한 후 소스를 복사하면 go mod vendor 에서 수정된 부분이 없으면 해당 layer 를 재사용하기 때문에 매번 다운로드를 하지 않는다.  

 

# vi Dockerfile

FROM golang:1.16.3-stretch AS builder
LABEL AUTHOR Seungkyu Ahn (seungkyua@gmail.com)

RUN mkdir -p /build
WORKDIR /build

COPY go.mod .
COPY go.sum .
RUN go mod vendor
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/tksinfo ./cmd/server.go

RUN mkdir -p /dist
WORKDIR /dist
RUN cp /build/bin/tksinfo ./tksinfo




FROM golang:alpine3.13

RUN mkdir -p /app
WORKDIR /app

COPY --chown=0:0 --from=builder /dist /app/
EXPOSE 9111

ENTRYPOINT ["/app/tksinfo"]
CMD ["--port", "9111"]
반응형
Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

반응형

2021년 4월 Golang 의 최신 버전은 1.16.x 입니다.

 

go 프로그램을 실행파일로 컴파일 하면 default 는 dynamic library 로 만들어 집니다.

 

아무리 OS 와 architecture 에 맞춰서 cross compile 을 했다고 해도 링크된 모듈이 존재하지 않으면 에러가 납니다.

특히 docker 로 실행할 경우 이런 문제를 자주 겪게 됩니다.

 

1.15 버전 이상에서는 CGO_ENABLED=0 환경 변수로 static library 로 만들 수 있습니다. 참고로 1.14 버전 이하에서는 -tags 옵션을 사용할 수 있습니다.

 

아래 Makefile 은 이 부분을 고려해서 만들었습니다.

GOOS는 OS 의 종류를 GOARCH 는 Architecture 에 맞춰 실행파일을 만듭니다.

 

$ vi Makefile

.PHONY: build clean docker

default: build

all: build docker

build: build-darwin build-linux

build-darwin:
	CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o bin/tksinfo-darwin-amd64 ./cmd/server.go
	CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o bin/tksinfo-appclient-darwin-amd64 ./examples/application/client.go

build-linux:
	CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/tksinfo-linux-amd64 ./cmd/server.go
	CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/tksinfo-appclient-linux-amd64 ./examples/application/client.go

clean:
	rm -rf ./bin

docker:
	docker build --no-cache -t seungkyua/tksinfo -f Dockerfile .
반응형
Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

반응형

Istio 의 설치 순서는 다음과 같다.

사전에 Prometheus 와 EasticSearch 는 설치되어 있다고 가정한다.

  1. istio operator 설치
  2. istio control plane 을 위한 istio custom resource 생성
  3. 서비스별 gateway 설치
  4. Jaeger 설치
  5. Kiali 설치

 

1. istio operator 설치

istio operator 를 설치하기 전에 istioctl 명령을 사용할 수 있게 파일을 다운로드 한다.

$ mkdir -p ~/ahnsk/istio && cd ~/ahnsk/istio

$ curl -L https://git.io/getLatestIstio | ISTIO_VERSION=1.9.1 sh -

$ cd ~/ahnsk/istio/istio-1.9.1

 

$ cp bin/istioctl /usr/local/bin/istioctl

 

istio operator 는 helm chart 로 설치하며, 따로 helm repo 를 등록하지 않고 istio source 를 다운받아 설치한다.

먼저, istio 소스를 다운 받는다.

$ cd ~/ahnsk/istio

$ git clone https://github.com/istio/istio.git istio-operator

$ cd istio-operator

$ git checkout -b tag_1.9.1 tags/1.9.1

 

istio operator 를 helm 으로 설치한다.

istio 는 control plane 을 canary upgrade  가 가능하도록 revision tag 로 구분할 수 있게 권장하고 있다. 그리고 istio-operator 네임스페이스에 operator 를 설치하고, istio-system 네임스페이스에 istio control plane 을 설치한다.

operator 를 생성할 때 istio-operator 네임스페이스는 자동으로 생성되나 istio-system 네임스페이스는 operator 를 설치하기 전에 수동으로 생성해 놓아야 한다.

$ cd ~/ahnsk/istio

$ vi istio-operator-values.yaml

---

revision: "1-9-1"

operatorNamespace: istio-operator

watchedNamespaces: istio-system

operator:

  resources:

    limits:

      cpu: 4

      memory: 4Gi

    requests:

      cpu: 2

      memory: 2Gi

 

$ kubectl create ns istio-system

$ helm upgrade -i istio-operator ./istio-operator/manifests/charts/istio-operator -f istio-operator-values.yaml -n istio-system

 

2. istio control plane 설치

istio control plane 은 istiod 라는 pod 로 설치된다. operator 가 있으므로 아래와 같이 custom resource 를 생성하면 자동으로 istio control plane 이 설치되는 구조이다.

custom resource 를 아래와 같이 생성한다.

$ vi istio-cr-1-9-1.yaml

---

apiVersion: install.istio.io/v1alpha1

kind: IstioOperator

metadata:

  namespace: istio-system

  name: istio-controlplane

spec:

  revision: "1-9-1"

  profile: default

  meshConfig:

    accessLogFile: /dev/stdout

    enableTracing: true

    enablePrometheusMerge: true

    defaultConfig:

      discoveryAddress: istiod-1-9-1.istio-system.svc:15012

      proxyMetadata: {}

      tracing:

        zipkin:

          address: jaeger-operator-jaeger-collector.istio-system:9411

        sampling: 100.0

  values:

    global:

      logging:

        level: "default:info"

      istioNamespace: istio-system

  components:

    pilot:

      k8s:

        env:

        - name: PILOT_TRACE_SAMPLING

          value: "100"

        resources:

          requests:

            cpu: 1000m

            memory: 1024Mi

        hpaSpec:

          maxReplicas: 10

          minReplicas: 2

        nodeSelector:

          taco-istio: enabled

    egressGateways:

    - name: istio-egressgateway

      namespace: istio-system

      enabled: true

      k8s:

        resources:

          requests:

            cpu: 1000m

            memory: 1024Mi

        hpaSpec:

          maxReplicas: 10

          minReplicas: 2

        nodeSelector:

          taco-istio: enabled

    ingressGateways:

    - name: istio-ingressgateway

      namespace: istio-system

      enabled: true

      k8s:

        resources:

          requests:

            cpu: 1000m

            memory: 1024Mi

        hpaSpec:

          maxReplicas: 10

          minReplicas: 2

        nodeSelector:

          taco-istio: enabled

        service:

          type: NodePort

          ports:

          - name: status-port

            port: 15021

            targetPort: 15021

          - name: http2

            port: 80

            targetPort: 8080

            nodePort: 31080

          - name: https

            port: 443

            targetPort: 8443

            nodePort: 30443

          - name: tcp

            port: 31400

            targetPort: 31400

          - name: tls

            port: 15443

            targetPort: 15443

  • revision 은 control plane 을 구별하기 위해서 사용한다.
  • meshConfig 는 istiod 와 envoy proxy 가 서로 연결되는 정보를 나타내며 discoveryAddress 는 control plane 인 istiod 의 service url 을 tracing 은 Jaeger 정보를 저장할 데이터소스 url 이다. 여기서는 jaeger tracing backend 로 elastic search 를 사용하고 있다. meshConfig 의 값은 istiod 가 설치되는 istio-system 네임스페이스에 istiod-1-9-1 이라는 이름의 ConfigMap 으로 저장된다.
  • components 는 pilot(istiod), ingressGateway, egressGateway 에 대한 설치 정보이다. hpa 로 auto scaling 을 활용하기 위해서는 kubernetes cluster 에 metric-server 가 설치되어 있어야 한다.

 

아래와 같이 custom resource 를 생성한다.

사전에 node-selector 로 어느 서버에 istiod 와 gateway 를 설치할 수 있는지 지정할 수 있다.

$ kubectl label node k1-node03 taco-istio=enabled

$ kubectl label node k1-node04 taco-istio=enabled

$ kubectl label node k1-node05 taco-istio=enabled

 

$ kubectl apply -f istio-cr-1-9-1.yaml

 

설치 현황은 아래 명령으로 확인할 수 있다.

$ kubectl get iop -n istio-system

-----------------------------------------------

NAME                   REVISION   STATUS    AGE

istio-controlplane     1-9-1      HEALTHY   44h

 

3. 서비스별 gateway 추가 설치

gateway 는 서비스별로 추가할 수 있다. 이 또한 custom resource 만 생성하면 되며 custom resource 는 아래와 같다.

$ vi istio-gateway-cr.yaml

---

apiVersion: install.istio.io/v1alpha1

kind: IstioOperator

metadata:

  namespace: istio-system

  name: istio-gateway-sample

spec:

  revision: "1-9-1"

  profile: empty

  values:

    global:

      logging:

        level: "default:info"

      istioNamespace: istio-system

  components:

    ingressGateways:

    - name: istio-ingressgateway-istio-gateway-sample

      namespace: istio-gateway-sample

      label:

        app: istio-ingressgateway-istio-gateway-sample

        istio: ingressgateway-istio-gateway-sample

      enabled: true

      k8s:

        resources:

          requests:

            cpu: 1000m

            memory: 1024Mi

        hpaSpec:

          maxReplicas: 10

          minReplicas: 2

        nodeSelector:

          taco-istio: enabled

        service:

          type: NodePort

          ports:

          - name: status-port

            port: 15021

            targetPort: 15021

          - name: http2

            port: 80

            targetPort: 8080

            nodePort: 31081

          - name: https

            port: 443

            targetPort: 8443

            nodePort: 31443

          - name: tcp

            port: 31400

            targetPort: 31400

          - name: tls

            port: 15443

            targetPort: 15443

  • profile 값은 empty 로 지정한다. empty 는 istiod 를 설치하지 않겠다는 뜻이다.
  • Gateway  에 label 은 중요하다. default label 값은 app=istio-ingressgateway 와 istio=ingressgateway 이다. Gateway 를 여러개 설치하면 서비스별로 VirtualService 와 연결해야 하는데 이 때 활용되는 것이 label 이다. 그러니 Gateway 별로 구별할 수 있게 label 을 서로 다르게 주는 것이 중요하다.
  • 새로운 네임스페이스에 생성된 Gateway 에 istiod 와 연결할 url 정보를 주는 것이 중요하다. 그런데 그 정보를 갖고 있는 meshConfig 에 넣어도 새로운 네임스페이스에 istio-1-9-1 ConfigMap 이 생성되지 않는다. 그래서 istio-1-9-1 ConfigMap 은 수동으로 설치해 주어야 한다.

 

Gateway 를 설치할 네임스페이스 생성과 그 네임스페이스에 istio-system 에 있는 istio-1-9-1 ConfigMap 을 복사하여 생성한다.

$ kubectl create ns istio-gateway-sample

 

$ kubectl get cm istio-1-9-1 -n istio-system -o yaml \

| grep -v '^\s*namespace:\s' \

| kubectl apply -f -n istio-gateway-sample -

 

custom resource 를 생성하여 Gateway 를 추가로 설치한다.

$ kubectl apply -f istio-gateway-cr.yaml

 

설치된 정보를 확인한다.

$ kubectl get iop -A

----------------------------------------------------------------

NAMESPACE      NAME                   REVISION   STATUS    AGE

istio-system   istio-controlplane     1-9-1      HEALTHY   45h

istio-system   istio-gateway-sample   1-9-1      HEALTHY   42h

 

 

 

# istioctl proxy-status

-----------------------------------------------------------------

NAME                                                                                CDS        LDS        EDS        RDS          ISTIOD                            VERSION

api-gateway-6f87d9477f-xg5dq.default                                                SYNCED     SYNCED     SYNCED     SYNCED       istiod-1-9-1-58ff56d6f8-dftbh     1.10-alpha.ba8228cc703fa11542c3e97c1702688d072152a1

details-v1-6f769b44-hzj8v.default                                                   SYNCED     SYNCED     SYNCED     SYNCED       istiod-1-9-1-58ff56d6f8-25z28     1.10-alpha.ba8228cc703fa11542c3e97c1702688d072152a1

istio-egressgateway-66cb5c46c7-c9q4b.istio-system                                   SYNCED     SYNCED     SYNCED     NOT SENT     istiod-1-9-1-58ff56d6f8-dftbh     1.10-alpha.f88f93ff2b8172b37c83d6066363d76b4477bd2d

istio-egressgateway-66cb5c46c7-qjrwj.istio-system                                   SYNCED     SYNCED     SYNCED     NOT SENT     istiod-1-9-1-58ff56d6f8-25z28     1.10-alpha.f88f93ff2b8172b37c83d6066363d76b4477bd2d

istio-ingressgateway-684d9c7755-brtsv.istio-system                                  SYNCED     SYNCED     SYNCED     SYNCED       istiod-1-9-1-58ff56d6f8-25z28     1.10-alpha.f88f93ff2b8172b37c83d6066363d76b4477bd2d

istio-ingressgateway-684d9c7755-dvtrd.istio-system                                  SYNCED     SYNCED     SYNCED     SYNCED       istiod-1-9-1-58ff56d6f8-dftbh     1.10-alpha.f88f93ff2b8172b37c83d6066363d76b4477bd2d

istio-ingressgateway-istio-gateway-sample-6d6998fc44-rnfnr.istio-gateway-sample     SYNCED     SYNCED     SYNCED     SYNCED       istiod-1-9-1-58ff56d6f8-dftbh     1.10-alpha.f88f93ff2b8172b37c83d6066363d76b4477bd2d

istio-ingressgateway-istio-gateway-sample-6d6998fc44-twcqp.istio-gateway-sample     SYNCED     SYNCED     SYNCED     SYNCED       istiod-1-9-1-58ff56d

 

4. sidecar auto injection 을 위한 레이블 설정

Istio 를 Operator 를 사용해서 revision 값을 주면 sidecar 를 자동으로 injection 하기 위해서 더이상 istio-injection=enabled 와 같은 Label을 쓰지 않는다. 위에 처럼 label 을 변경줘야 한다. istio-injection=enabled 으로 설명하는 문서들이 있으면 demo 와 같은 simple 한 설치이거나 이전 설치 방법이다.

 

$ kubectl label ns default istio-injection=enabled # 소용없음
$ kubectl label ns default istio.io/rev=1-9-1

 

 

 

Jager 와 kiali 는 다음에...

 

 

 

 

반응형
Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

  1. BlogIcon 뉴비뉴 2021.03.23 18:22 신고  댓글주소  수정/삭제  댓글쓰기

    $ kubectl get cm istio-1-9-1 -n istio-system -o yaml \
    | grep -v '^\s*namespace:\s' \
    | kubectl apply -f -n istio-gateway-sample -

    마지막 줄 저는 이렇게 해야 동작하네요! kubectl apply -f - -n istio-gateway-sample
    좋은 글 잘 읽었습니다!

반응형

마이크로서비스 아키텍처를 공부하다 보면 Circuit Breaker 에 대해서 알게 된다.

여태까지 나는 Circuit Breaker 는 단순히 서비스를 차단해주는 역할을 주라고 생각했는데 그게 아니었음.. ㅠㅠ

 

Circuit Breaker 의 진정한 목적은 Backpressure 를 downstream 에 적용하는 것이라고 할 수 있다. (apply backpressure downstream)

Backpressure 의 의미는 아래 글을 참조..

medium.com/@jayphelps/backpressure-explained-the-flow-of-data-through-software-2350b3e77ce7

 

Backpressure explained — the flow of data through software

Backpressure is something nearly every software engineer will have to deal with at some point, and for some it’s a frequent problem. But…

medium.com

간단히 설명하면 A, B, C 라는 서비스가 각각 D 라는 하나의 서비스를 호출한다고 가정하자. 이 때 D 서비스의 처리량 이상을 A 서비스가 호출한다면, B, C 서비스도 더이상 D 서비스를 호출하여 응답을 받을 수 없다. 그래서 A 서비스가 D를 호출하는 것을 buffer 에 저장하여 잠시 늦추는 효과를 준다면 D 서비스는 이상없이 동작하게 되고 B, C 서비스도 정상적인 응답을 받을 수 있다.

여기서 A서비스에 적용한 것이 Backpressure 이다.

 

Backpressure 를 적용하기 위한 전략은 다음과 같다.

  • Control the producer (slow down/speed up is decided by consumer)
  • Buffer (accumulate incoming data spikes temporarily)
  • Drop (sample a percentage of the incoming data)

오늘 하나 더 배움에 감사하며~~

 

 

 

반응형
Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

반응형

CNCF Project 에 대한 내용을 간략한 아이콘 및 다이어 그램으로 설명한 자료입니다.

웬만한 프로젝트는 모두 보여준 듯 하네요. ^^

 

drive.google.com/file/d/1-uS_jEKakOUxjYKYV1CH3z7CYqOuqrPx/view?usp=sharing

반응형
Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

반응형

KubeCon 2일째 주요 Keynote 내용은 OpenTelemetry, Scalable Kubernetes Cluster, CNCF Tools 입니다.

 

먼저 OpenTelemetry 에서는 아래의 내용들을 이야기 했죠.

 

OpenTelemetry 는 2019년에 발표했는데 OpenCensus 와 OpenTracing 을 합쳤습니다.

OpenTelemetry 가 나온 이유 중 하나는 Vendor lock in 을 피하기 위해서입니다.

 

개념은 아주 간단합니다. Collector 간의 연결입니다.

 

데이터 수집 -> 변경 -> 보내기 형태의 pipeline 구조로 구성됩니다.

 

Collector 가 multiple flow 를 받을 수 있습니다.

 

아래 OpenTelemetry 를 방문하면 더 많은 정보를 얻을 수 있습니다.

 

Scalable Kubernetes Cluster 는 여러 가지 고려 사항을 이야기 했습니다.

15,000 노드 클러스터인 경우에 고려할 사항은 etcd 입니다.

모든 정보가 etcd 에 저장될 텐데 그것을 처리할 수 있는 용량을 항상 고려해야 합니다.

 

apimachinery 도 고려해야 합니다.

많은 리소스들이 저장되어 있는데 이 중에서 리소스를 select 를 할 때 적절하게 조회하고 이를 관리할 수 있는 API 용량이 필요합니다.

 

Networking 부분에서는 돌아다니는 데이터 양을 고려해야 합니다.

Kube-proxy 가 노드마다 떠 있고 endpoint 가 수정될 때 마다 이를 api 서버로 보냅니다. 예를 들어 5000개의 서비스 pod 가 떠 있다면 1M 정도의 데이터 양을 보내는데 노드가 5000개 있다면 보내는 데이터 양은 5G 나 됩니다.

이를 해결하기 위해서 endpoint slicing 을 사용합니다.

 

Secret 과 ConfigMap 이 pod 가 생성되는 로컬에 저장되는 스토리지도 고려해야 합니다.

 

 

 

 

 

반응형
Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요