[쿠버네티스 심화] 투두 리스트 앱 StatefulSets 분석

Jisu·2023년 12월 6일

Kubernetes

목록 보기
7/12
post-thumbnail

배경

지난 시간에는 Helm Chart를 이용해서
Helm chart로 배포된 앱들의 명세파일을 복습해보자. 이를 통해 각각의 work load resource들이 어떤 역할을 하는지 파악해보자.


네임스페이스 분석

helm-test 네임스페이스에서 Statefulsets Pod 3개 + Deployment Pod 3개가 돌아가고 있다. StatefulSets로 배포된 mysql은 파드 뒤에 넘버링이 되어있는 것을 볼 수 있다.


StatefulSets YAML 분석

yaml 코드에서 ** 부분이 중요표시한 부분이다.

아무래도 핵심은 mysql 컨테이너 관련 설정과 PVC template 부분이 아닐까 싶다.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  annotations:
    meta.helm.sh/release-name: mysql-helm
    meta.helm.sh/release-namespace: helm-test
  creationTimestamp: "2023-10-30T00:19:50Z"
  generation: 2
  labels:
    app.kubernetes.io/component: primary
    app.kubernetes.io/instance: mysql-helm
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: mysql
    app.kubernetes.io/version: 8.0.34
    helm.sh/chart: mysql-9.12.3
  **name: mysql-helm
  namespace: helm-test**
  resourceVersion: "519130"
  uid: b6287b10-f656-4bdb-ada0-6613f3cf80fa
spec:
  persistentVolumeClaimRetentionPolicy:
    whenDeleted: Retain
    whenScaled: Retain
  podManagementPolicy: OrderedReady
  **replicas: 3**
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/component: primary
      app.kubernetes.io/instance: mysql-helm
      app.kubernetes.io/name: mysql
  serviceName: mysql-helm
  template:
    metadata:
      annotations:
        checksum/configuration: 4248c402456d9aba0d80cd1f28d8f299a7bff9a88417098a4bba6fdcf60c4f94
      creationTimestamp: null
      labels:
        app.kubernetes.io/component: primary
        app.kubernetes.io/instance: mysql-helm
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/name: mysql
        app.kubernetes.io/version: 8.0.34
        helm.sh/chart: mysql-9.12.3
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchLabels:
                  app.kubernetes.io/instance: mysql-helm
                  app.kubernetes.io/name: mysql
              topologyKey: kubernetes.io/hostname
            weight: 1
      containers:
      **- env:
        - name: BITNAMI_DEBUG
          value: "false"
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              key: mysql-root-password
              name: mysql-helm
        - name: MYSQL_DATABASE**
          **value: my_database**
        **image: docker.io/bitnami/mysql:8.0.34-debian-11-r56**
        imagePullPolicy: IfNotPresent
        livenessProbe:
          exec:
            command:
            - /bin/bash
            - -ec
            - |
              password_aux="${MYSQL_ROOT_PASSWORD:-}"
              if [[ -f "${MYSQL_ROOT_PASSWORD_FILE:-}" ]]; then
                  password_aux=$(cat "$MYSQL_ROOT_PASSWORD_FILE")
              fi
              mysqladmin status -uroot -p"${password_aux}"
          failureThreshold: 3
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        **name: mysql
        ports:
        - containerPort: 3306
          name: mysql
          protocol: TCP**
        readinessProbe:
          exec:
            command:
            - /bin/bash
            - -ec
            - |
              password_aux="${MYSQL_ROOT_PASSWORD:-}"
              if [[ -f "${MYSQL_ROOT_PASSWORD_FILE:-}" ]]; then
                  password_aux=$(cat "$MYSQL_ROOT_PASSWORD_FILE")
              fi
              mysqladmin status -uroot -p"${password_aux}"
          failureThreshold: 3
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        resources: {}
        securityContext:
          runAsNonRoot: true
          runAsUser: 1001
        startupProbe:
          exec:
            command:
            - /bin/bash
            - -ec
            - |
              password_aux="${MYSQL_ROOT_PASSWORD:-}"
              if [[ -f "${MYSQL_ROOT_PASSWORD_FILE:-}" ]]; then
                  password_aux=$(cat "$MYSQL_ROOT_PASSWORD_FILE")
              fi
              mysqladmin status -uroot -p"${password_aux}"
          **failureThreshold: 10
          initialDelaySeconds: 15
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1**
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /bitnami/mysql
          name: data
        - mountPath: /opt/bitnami/mysql/conf/my.cnf
          name: config
          subPath: my.cnf
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext:
        fsGroup: 1001
      serviceAccount: mysql-helm
      serviceAccountName: mysql-helm
      terminationGracePeriodSeconds: 30
      **volumes:
      - configMap:
          defaultMode: 420
          name: mysql-helm
        name: config**
  updateStrategy:
    type: RollingUpdate
  **volumeClaimTemplates:
  - apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      creationTimestamp: null
      labels:
        app.kubernetes.io/component: primary
        app.kubernetes.io/instance: mysql-helm
        app.kubernetes.io/name: mysql
      name: data
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 8Gi
      volumeMode: Filesystem
    status:
      phase: Pending**
status:
  **availableReplicas: 3**
  collisionCount: 0
  currentReplicas: 3
  currentRevision: mysql-helm-7695566df9
  observedGeneration: 2
  readyReplicas: 3
  replicas: 3
  updateRevision: mysql-helm-7695566df9
  updatedReplicas: 3

a. Container 속성 분석

        **name: mysql
        ports:
        - containerPort: 3306
          name: mysql
          protocol: TCP**
  • Container 이름은 mysql
  • 포트 개방은 3306, mysql로 DNS 네이밍
    • Headless service에서 targetport를 mysql로 지정하는게 여기서 네이밍을 해주기 때문!
  • TCP 프로토콜 사용

      containers:
      **- env:
        - name: BITNAMI_DEBUG
          value: "false"
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              key: mysql-root-password
              name: mysql-helm
        - name: MYSQL_DATABASE**
          **value: my_database**
        **image: docker.io/bitnami/mysql:8.0.34-debian-11-r56**
  • 이미지는 docker.io/bitnami/mysql:8.0.34-debian-11-r56 사용
  • root 비밀번호는 secret에 명시된 사항 사용
  • 기본 mysql database로 my_database 생성

b. PVC

**volumeClaimTemplates:
  - apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      creationTimestamp: null
      labels:
        app.kubernetes.io/component: primary
        app.kubernetes.io/instance: mysql-helm
        app.kubernetes.io/name: mysql
      name: data
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 8Gi
      volumeMode: Filesystem**
  • 각 Pod에는 data라는 이름의 PVC가 생성되며 8 기가바이트의 스토리지를 요청
  • PVC는 ReadWriteOnce 액세스 모드를 사용. Pod당 한 번에 하나의 Pod만 해당 PVC에 액세스 가능

C. Probe

probe는 컨테이너의 상태를 확인하기 위한 기능이다.

컨테이너의 정상 작동 여부를 주기적으로 확인하고, 필요에 따라 해당 컨테이너를 재시작하거나 서비스 트래픽을 분산하는 등의 조치를 취할 수 있다. (probe는 검사하다 라는 뜻을 가짐)

    startupProbe:
          exec:
            command:
            - /bin/bash
            - -ec
            - |
              password_aux="${MYSQL_ROOT_PASSWORD:-}"
              if [[ -f "${MYSQL_ROOT_PASSWORD_FILE:-}" ]]; then
                  password_aux=$(cat "$MYSQL_ROOT_PASSWORD_FILE")
              fi
              mysqladmin status -uroot -p"${password_aux}"
          **failureThreshold: 10
          initialDelaySeconds: 15
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1**

livenessProbe: Pod의 상태를 확인하는 데 사용되는 프로브
MySQL이 정상적으로 작동하는지 확인하기 위해 주기적으로 mysqladmin status 명령을 실행한다.

  • failureThreshold: 프로브가 실패로 표시되기 전에 몇 번의 연속 실패가 허용되는지 표기
  • initialDelaySeconds: Pod이 처음 시작된 후 프로브가 시작되기까지의 대기 시간
  • periodSeconds: 프로브 간의 주기적인 검사 간격
  • successThreshold: 프로브가 성공으로 표시되기 위해 필요한 연속 성공 횟수
  • timeoutSeconds: 각 프로브의 타임아웃 시간

D. Volume

**volumes:
- configMap:
    defaultMode: 420
    name: mysql-helm
  name: config**
  • MySQL Pod의 설정을 ConfigMap에서 가져와 마운트한다.
  • ConfigMap은 mysql-helm이라는 이름으로 지정되어 있고 그 안에 세부 설정이 있음

참고 - ConfigMap

ConfigMap은 Kubernetes에서 설정 데이터를 저장하는 데 사용되는 리소스 타입이다.

애플리케이션 설정, 환경 변수, 명령행 매개변수 등과 같은 설정 데이터를 저장하고 ConfigMap을 사용하면 설정을 별도로 관리하고 필요에 따라 변경할 수 있다.

apiVersion: v1
data:
  my.cnf: |-
    [mysqld]
    default_authentication_plugin=mysql_native_password
    skip-name-resolve
    explicit_defaults_for_timestamp
    basedir=/opt/bitnami/mysql
    plugin_dir=/opt/bitnami/mysql/lib/plugin
    port=3306
    socket=/opt/bitnami/mysql/tmp/mysql.sock
    datadir=/bitnami/mysql/data
    tmpdir=/opt/bitnami/mysql/tmp
    max_allowed_packet=16M
    bind-address=*
    pid-file=/opt/bitnami/mysql/tmp/mysqld.pid
    log-error=/opt/bitnami/mysql/logs/mysqld.log
    character-set-server=UTF8
    collation-server=utf8_general_ci
    slow_query_log=0
    long_query_time=10.0

    [client]
    port=3306
    socket=/opt/bitnami/mysql/tmp/mysql.sock
    default-character-set=UTF8
    plugin_dir=/opt/bitnami/mysql/lib/plugin

    [manager]
    port=3306
    socket=/opt/bitnami/mysql/tmp/mysql.sock
    pid-file=/opt/bitnami/mysql/tmp/mysqld.pid
kind: ConfigMap
metadata:
  annotations:
    meta.helm.sh/release-name: mysql-helm
    meta.helm.sh/release-namespace: helm-test
  creationTimestamp: "2023-10-30T00:19:50Z"
  labels:
    app.kubernetes.io/component: primary
    app.kubernetes.io/instance: mysql-helm
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: mysql
    app.kubernetes.io/version: 8.0.34
    helm.sh/chart: mysql-9.12.3
  name: mysql-helm
  namespace: helm-test
  resourceVersion: "502593"
  uid: 500303e1-40e5-462c-a3c2-3abd7fa19e05
profile
기술 공유를 즐기는 DevOps Engineer 장지수입니다.

0개의 댓글