본문으로 바로가기 본문 바로가기
WIKI 기술 지식 베이스

Typha 설치하기

원문 보기 위키 갱신

Typha는 Kubernetes API 서버와 각 노드 데몬 사이에서 데이터스토어 읽기를 분산해 주는 컴포넌트예요. 이 문서는 Calico 설치 난이도 높은 방식(hard way) 시리즈의 일부로, Typha를 직접 설치하는 절차를 안내해요. CA 인증서 생성부터 RBAC 구성, Deployment와 Service 배포, TLS 동작 확인까지 차근차근 따라 해 보세요.

출처: 문서

본문

Typha는 Kubernetes API 서버와 calico/node에서 실행되는 Felix, confd 같은 노드별 데몬 사이에 위치해요. Typha는 이 데몬들이 사용하는 Kubernetes 리소스와 Calico 커스텀 리소스를 감시(watch)하고, 리소스가 바뀔 때마다 변경 사항을 데몬들에게 전파해요. 덕분에 Kubernetes API 서버가 처리해야 하는 watch 수가 줄고 클러스터 확장성이 좋아져요.

인증서 준비하기

calico/node와 Typha가 안전하게 통신하도록 상호 인증 TLS를 사용할 거예요. 이 섹션에서는 인증 기관(CA)을 생성하고, 이 CA로 Typha 인증서에 서명해요.

CA 인증서와 키 만들기

openssl req -x509 -newkey rsa:4096 \
                  -keyout typhaca.key \
                  -nodes \
                  -out typhaca.crt \
                  -subj "/CN=Calico Typha CA" \
                  -days 365

CA 인증서를 Typha와 calico/node가 접근할 ConfigMap에 저장해요.

kubectl create configmap -n kube-system calico-typha-ca --from-file=typhaca.crt

Typha 키와 인증서 서명 요청(CSR) 만들기

openssl req -newkey rsa:4096 \
           -keyout typha.key \
           -nodes \
           -out typha.csr \
           -subj "/CN=calico-typha"

이 인증서는 Common Name(CN)으로 calico-typha를 제시해요. calico/node는 이 이름을 검증하도록 구성될 거예요.

CA로 Typha 인증서 서명하기

openssl x509 -req -in typha.csr \
                  -CA typhaca.crt \
                  -CAkey typhaca.key \
                  -CAcreateserial \
                  -out typha.crt \
                  -days 365

Typha 키와 인증서를 Typha가 접근할 시크릿에 저장해요.

kubectl create secret generic -n kube-system calico-typha-certs --from-file=typha.key --from-file=typha.crt

RBAC 준비하기

Typha 실행에 사용할 ServiceAccount를 만들어요.

kubectl create serviceaccount -n kube-system calico-typha

Calico 데이터스토어 객체를 watch할 수 있는 권한을 가진 Typha용 클러스터 롤을 정의해요.

kubectl apply -f - <<EOF
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: calico-typha
rules:
  - apiGroups: [""]
    resources:
      - pods
      - namespaces
      - serviceaccounts
      - endpoints
      - services
      - nodes
    verbs:
      - watch
      - list
      - get
  - apiGroups: ["networking.k8s.io"]
    resources:
      - networkpolicies
    verbs:
      - watch
      - list
  - apiGroups: ["crd.projectcalico.org"]
    resources:
      - globalfelixconfigs
      - felixconfigurations
      - bgppeers
      - globalbgpconfigs
      - bgpconfigurations
      - ippools
      - ipamblocks
      - globalnetworkpolicies
      - globalnetworksets
      - networkpolicies
      - clusterinformations
      - hostendpoints
      - blockaffinities
      - networksets
    verbs:
      - get
      - list
      - watch
  - apiGroups: ["crd.projectcalico.org"]
    resources:
      #- ippools
      #- felixconfigurations
      - clusterinformations
    verbs:
      - get
      - create
      - update
EOF

클러스터 롤을 calico-typha ServiceAccount에 바인딩해요.

kubectl create clusterrolebinding calico-typha --clusterrole=calico-typha --serviceaccount=kube-system:calico-typha

Deployment 설치하기

Typha는 calico/node가 필요로 하고, calico/node는 파드 네트워크를 구성하므로, 닭과 달걀 문제를 피하려고 Typha를 호스트 네트워크 파드로 실행해요. 롤링 업데이트 중에도 단일 장애로 Typha를 사용할 수 없게 되지 않도록 레플리카 3개로 실행해요.

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: calico-typha
  namespace: kube-system
  labels:
    k8s-app: calico-typha
spec:
  replicas: 3
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      k8s-app: calico-typha
  template:
    metadata:
      labels:
        k8s-app: calico-typha
      annotations:
        cluster-autoscaler.kubernetes.io/safe-to-evict: 'true'
    spec:
      hostNetwork: true
      tolerations:
        # Mark the pod as a critical add-on for rescheduling.
        - key: CriticalAddonsOnly
          operator: Exists
      serviceAccountName: calico-typha
      priorityClassName: system-cluster-critical
      containers:
      - image: calico/typha:v3.8.0
        name: calico-typha
        ports:
        - containerPort: 5473
          name: calico-typha
          protocol: TCP
        env:
          # Disable logging to file and syslog since those don't make sense in Kubernetes.
          - name: TYPHA_LOGFILEPATH
            value: "none"
          - name: TYPHA_LOGSEVERITYSYS
            value: "none"
          # Monitor the Kubernetes API to find the number of running instances and rebalance
          # connections.
          - name: TYPHA_CONNECTIONREBALANCINGMODE
            value: "kubernetes"
          - name: TYPHA_DATASTORETYPE
            value: "kubernetes"
          - name: TYPHA_HEALTHENABLED
            value: "true"
          # Location of the CA bundle Typha uses to authenticate calico/node; volume mount
          - name: TYPHA_CAFILE
            value: /calico-typha-ca/typhaca.crt
          # Common name on the calico/node certificate
          - name: TYPHA_CLIENTCN
            value: calico-node
          # Location of the server certificate for Typha; volume mount
          - name: TYPHA_SERVERCERTFILE
            value: /calico-typha-certs/typha.crt
          # Location of the server certificate key for Typha; volume mount
          - name: TYPHA_SERVERKEYFILE
            value: /calico-typha-certs/typha.key
        livenessProbe:
          httpGet:
            path: /liveness
            port: 9098
            host: localhost
          periodSeconds: 30
          initialDelaySeconds: 30
        readinessProbe:
          httpGet:
            path: /readiness
            port: 9098
            host: localhost
          periodSeconds: 10
        volumeMounts:
        - name: calico-typha-ca
          mountPath: "/calico-typha-ca"
          readOnly: true
        - name: calico-typha-certs
          mountPath: "/calico-typha-certs"
          readOnly: true
      volumes:
      - name: calico-typha-ca
        configMap:
          name: calico-typha-ca
      - name: calico-typha-certs
        secret:
          secretName: calico-typha-certs
EOF

TYPHA_CLIENTCN을 calico-node로 설정했는데, 이는 다음 실습에서 calico/node가 사용할 인증서에 넣을 common name이에요.

Typha가 인스턴스 세 개로 잘 떠 있는지 확인해요.

kubectl get pods -l k8s-app=calico-typha -n kube-system

결과:

NAME                            READY   STATUS    RESTARTS   AGE
calico-typha-66498ddfbd-2pzsr   1/1     Running   0          69s
calico-typha-66498ddfbd-lrtzw   1/1     Running   0          50s
calico-typha-66498ddfbd-scckd   1/1     Running   0          62s

Service 설치하기

calico/node는 Kubernetes Service를 사용해 로드 밸런싱된 Typha 접근을 얻어요.

kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: calico-typha
  namespace: kube-system
  labels:
    k8s-app: calico-typha
spec:
  ports:
    - port: 5473
      protocol: TCP
      targetPort: calico-typha
      name: calico-typha
  selector:
    k8s-app: calico-typha
EOF

Typha가 TLS를 사용하는지 검증해요.

TYPHA_CLUSTERIP=$(kubectl get svc -n kube-system calico-typha -o jsonpath='{.spec.clusterIP}')
curl https://$TYPHA_CLUSTERIP:5473 -v --cacert typhaca.crt

결과

* Rebuilt URL to: https://10.103.120.116:5473/
*   Trying 10.103.120.116...
* TCP_NODELAY set
* Connected to 10.103.120.116 (10.103.120.116) port 5473 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: typhaca.crt
  CApath: /etc/ssl/certs
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS alert, Server hello (2):
* error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate
* stopped the pause stream!
* Closing connection 0
curl: (35) error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate

이 결과는 Typha가 TLS 인증서를 제시하고 있고, 우리 쪽에서 인증서를 제시하지 않았기 때문에 연결을 거부했다는 뜻이에요. 다음 실습에서 calico/node를 Typha가 받아들이는 인증서와 함께 배포할 거예요.

다음

calico/node 설치하기

더 알아보기 (Learn more)

Typha는 API 서버의 watch 부담을 덜어 주는 확장성 컴포넌트예요. TLS 검증 단계에서 인증서 없이 연결이 거부되는 것은 정상 동작이니, 실패로 오해하지 않도록 주의하세요.