linuxer-admin

PKOS-4Week

이번주 스터디는 K8S에서의 Pometheus Grafana 다.

이글은 chatgpt를 이용해서 삽질하는 리눅서를 담고있다.

프로메테우스는 아이콘이 불꽃 모양인데 정말 모니터링계에 불을 가져다준 혁신과도 같은 존재다. 이전에는 Nagios / Zabbix가 나눠먹고 있었다.

나는 이번에 뭘 모니터링 해볼까 고민하다가 HPA를 모니터링 해볼까한다.

먼저 내가 요즘 일하는 방식을 보여줄까한다.

바로 Chatgpt다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-deployment
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50

https://github.com/rakyll/hey

go 기반이라 bash로 수정해달라고 했다.

#!/bin/bash

SERVICE_IP=$(kubectl get svc nginx-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
CONCURRENCY=100
REQUESTS=50000

# Run load test
for i in $(seq 1 $CONCURRENCY); do
  (for j in $(seq 1 $(($REQUESTS / $CONCURRENCY))); do
    curl -s -o /dev/null http://${SERVICE_IP}/
  done) &
done

# Wait for all background processes to complete
wait

위의 Manifast 를 적용한 결과는 다음과 같다.

 k get all 
NAME                                    READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-7c6895c677-cblrh   1/1     Running   0          15s
pod/nginx-deployment-7c6895c677-s6b5c   1/1     Running   0          15s
pod/nginx-deployment-7c6895c677-smkxv   1/1     Running   0          15s

NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/nginx-service   LoadBalancer   100.66.65.216   <pending>     80:30979/TCP   15s

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   3/3     3            3           15s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-7c6895c677   3         3         3       15s

NAME                                            REFERENCE                     TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/nginx-hpa   Deployment/nginx-deployment   <unknown>/50%   3         10        3          19s

정말 잘동작한다.

이제 ingress 답변을 받았다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx-service
                port:
                  number: 80
k get ingress
NAME         CLASS    HOSTS   ADDRESS                                                                     PORTS   AGE
my-ingress   <none>   *       k8s-nginx-myingres-106681c1f1-1873214288.ap-northeast-2.elb.amazonaws.com   80      72s

ingress - svc - deployment - hpa 구조 같은건 이제 3분이면 나온다.

gpt가 알려준 스크립트중

kubectl get svc nginx-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

부분을

kubectl get ingress my-ingress -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'

다음과 같이 수정하였다.

curl k8s-nginx-myingres-106681c1f1-1873214288.ap-northeast-2.elb.amazonaws.com 
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

잘 뜬다.

이제 공격 간다

굉장한 스크립트 였다... 한방에 100개의 스크립트가 떴다...후....

근데 nginx 는 너무 가벼운 친구라...ㅠㅠ hpa 가 잘작동하지 않았다. 리미트를 준다.

        resources:
          limits:
            cpu: 15m
            memory: 10Mi
          requests:
            cpu: 15m
            memory: 10Mi
            
k get hpa
NAME        REFERENCE                     TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
nginx-hpa   Deployment/nginx-deployment   33%/50%   3         10        3          25m

좋다 적절하다.

이제 셋업은 다되었다. hpa 가 동작하는 대시보드와 hap 가 일정이상 동작해서 max 에 가 까워지면 알럿을 날릴거다.

Chatgpt에게 물었고, 비슷한 쿼리를 작성했다.

kube_horizontalpodautoscaler_status_desired_replicas{horizontalpodautoscaler="nginx-hpa", namespace="nginx"}

결과는 잘 작동한다. 그럼이걸 알럿을 보낼거다.

프로메테우스에서 graph로 grafana 에서 가져온 쿼리를 넣는다

1- avg(rate(kube_horizontalpodautoscaler_status_desired_replicas{horizontalpodautoscaler="nginx-hpa", namespace="nginx"}[1m]))

 k edit cm prometheus-kube-prometheus-stack-prometheus-rulefiles-0
configmap/prometheus-kube-prometheus-stack-prometheus-rulefiles-0 edited

edit 로 수정했다.

추가를 하다가 잘 안되서 helm에 있는 config를 뜯어봤다. 어떤구성인지,

     containers:
      - env:
        - name: BITNAMI_DEBUG
          value: "false"
        - name: NGINX_HTTP_PORT_NUMBER
          value: "8080"
        image: docker.io/bitnami/nginx:1.23.3-debian-11-r17
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 6
          initialDelaySeconds: 30
          periodSeconds: 10
          successThreshold: 1
          tcpSocket:
            port: http
          timeoutSeconds: 5
        name: nginx
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          initialDelaySeconds: 5
          periodSeconds: 5
          successThreshold: 1
          tcpSocket:
            port: http
          timeoutSeconds: 3
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      - command:
        - /usr/bin/exporter
        - -nginx.scrape-uri
        - http://127.0.0.1:8080/status
        image: docker.io/bitnami/nginx-exporter:0.11.0-debian-11-r44
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /metrics
            port: metrics
            scheme: HTTP
          initialDelaySeconds: 15
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 5
        name: metrics
        ports:
        - containerPort: 9113
          name: metrics
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /metrics
            port: metrics
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      serviceAccount: default
      serviceAccountName: default
      shareProcessNamespace: false
      terminationGracePeriodSeconds: 30

exporter 가 사이드카로 붙어서 모니터링을 하고있었다.

https://github.com/nginxinc/nginx-prometheus-exporter

온종일 삽질의 연속이다가 오늘또 k8s에서의 프로메테우스와 그라파나 패턴을 까보면서 helm을 써야할까 하는 고민이들었다. kustomize를 고민했는데 좀더 뭘깍을지 생각해봐야겠다.

Argo-WorkFlow/Events

이글은 Argo WorkFlow로 CI를 하려했던 나의 경험담을 담고있다.

Argo WorkFlow를 쓰려고 결심하고 리서칭하는 중이라면 AirFlow가 있다. 돌아가라.

Argo WorkFlow는 Flow마다 Pod를 생성한다. 그대가 원하는 패턴이 맞는지 다시한번 생각하라. 매 Flow 마다 Pod가 만들어 지는것이 맞는가? 그렇다면 맞다 Argo WorkFlow 다.

그럼다면 다시 묻는다 CI를 위해서 Argo를 찾는것인가? K8S에서 다양한 CRD에 익숙하고 강력한 러닝커브는 즐거움으로 생각되고 CNCF에 기여하는게 꿈이라면 말리지 않겠다. 잘왔다. Argo WorkFlow/Events다.

이 글에선 CI를 다룬다. 물론 글이 깊진 않다. 하지만 찍먹으론 충분한 수준으로 그대에게 전달할 것이다. 먼저 Argo-WorkFlow 를 설치해야한다.

Argo 를 이용한 CI의 길은 친절하지 않다. 먼저 WorkFlow 설치는 이렇다.

https://github.com/argoproj/argo-workflows/releases/download/v3.4.5/install.yaml

다운 받는다.

https://argoproj.github.io/argo-workflows/quick-start/

에는 포트포워딩을 하는 방식이지만 우리는 Ingress 를 이용할거다. 그러기 위해선 install.yaml을 수정해야한다.

친절하게 하나하나 다설명하고 싶지만 내 의욕이 그렇게 길지 않기 때문에 대충 설명하겠다.

https://github.com/Cloud-Linuxer/Argo-test/blob/main/Argo-WorkFlow-install.yaml

이파일을 다운받던가 아래처럼 수정하자.

1257 / 1258 라인을 을 추가해야한다. 그래야 백엔드가 HTTP로 동작하고 인증모드가 서버로 동작한다 혹시 쓰고싶다면 sso 를 붙여야한다.

k create ns argo
k apply -f Argo-WorkFlow-install.yaml 
customresourcedefinition.apiextensions.k8s.io/clusterworkflowtemplates.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/cronworkflows.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/workflowartifactgctasks.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/workfloweventbindings.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/workflows.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/workflowtaskresults.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/workflowtasksets.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/workflowtemplates.argoproj.io created
serviceaccount/argo created
serviceaccount/argo-server created
role.rbac.authorization.k8s.io/argo-role created
clusterrole.rbac.authorization.k8s.io/argo-aggregate-to-admin created
clusterrole.rbac.authorization.k8s.io/argo-aggregate-to-edit created
clusterrole.rbac.authorization.k8s.io/argo-aggregate-to-view created
clusterrole.rbac.authorization.k8s.io/argo-cluster-role created
clusterrole.rbac.authorization.k8s.io/argo-server-cluster-role created
rolebinding.rbac.authorization.k8s.io/argo-binding created
clusterrolebinding.rbac.authorization.k8s.io/argo-binding created
clusterrolebinding.rbac.authorization.k8s.io/argo-server-binding created
configmap/workflow-controller-configmap created
service/argo-server created
priorityclass.scheduling.k8s.io/workflow-controller created
deployment.apps/argo-server created
deployment.apps/workflow-controller created

CRD부터 SA role 등등 마지막으로 2개의 deployment를 만든다. 그럼 내가 추가한 설정이 잘추가 됬는 지 확인하고 싶다면 argo-server 의 시작 로그를 확인한다.

k logs argo-server-5779fd7868-nb77l 
time="2023-03-21T12:56:22.411Z" level=info msg="not enabling pprof debug endpoints"
time="2023-03-21T12:56:22.411Z" level=info authModes="[server]" baseHRef=/ managedNamespace= namespace=argo secure=false ssoNamespace=argo
time="2023-03-21T12:56:22.412Z" level=warning msg="You are running in insecure mode. Learn how to enable transport layer security: https://argoproj.github.io/argo-workflows/tls/"
time="2023-03-21T12:56:22.412Z" level=warning msg="You are running without client authentication. Learn how to enable client authentication: https://argoproj.github.io/argo-workflows/argo-server-auth-mode/"
time="2023-03-21T12:56:22.412Z" level=info msg="SSO disabled"
time="2023-03-21T12:56:22.422Z" level=info msg="Starting Argo Server" instanceID= version=v3.4.5
time="2023-03-21T12:56:22.422Z" level=info msg="Creating event controller" asyncDispatch=false operationQueueSize=16 workerCount=4
time="2023-03-21T12:56:22.425Z" level=info msg="GRPC Server Max Message Size, MaxGRPCMessageSize, is set" GRPC_MESSAGE_SIZE=104857600
time="2023-03-21T12:56:22.425Z" level=info msg="Argo Server started successfully on http://localhost:2746" url="http://localhost:2746"

automode 에 [server] 이 들어가있다면 정상적으로 먹은거다. 기본이 Clinet다. 그리고 서버 시작로그에 url 에 https 가 아니라 http 면 백엔드가 http 인거다.

여기까지 하면 이제 WorkFlow를 사용할 준비가 아직 안된거다. 이건 단순히 컨트롤러와 argo-server UI까지만 설치한거다.

우리는 이제 왜 내글의 제목이 Argo-WorkFlow/Events 인지 알게 된다.

Argo 프로젝트로 CI를 하기위해선 WF만으로는 할수없다. Events 를 써야한다.

https://github.com/Cloud-Linuxer/Argo-test/blob/main/Argo-Events-install.yaml

원래 Argo-WorkFlow 와 Argo-Events 는 namespace로 분리되어있지만 나는 이 CRD의 지저분함을 견딜수없어서 argo namespace 하나로 구성했다 Argo-Events-install.yaml 파일은 namespace를 수정한 파일이다.

 k apply -f Argo-Events-install.yaml 
customresourcedefinition.apiextensions.k8s.io/eventbus.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/eventsources.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/sensors.argoproj.io created
serviceaccount/argo-events-sa created
clusterrole.rbac.authorization.k8s.io/argo-events-aggregate-to-admin created
clusterrole.rbac.authorization.k8s.io/argo-events-aggregate-to-edit created
clusterrole.rbac.authorization.k8s.io/argo-events-aggregate-to-view created
clusterrole.rbac.authorization.k8s.io/argo-events-role created
clusterrolebinding.rbac.authorization.k8s.io/argo-events-binding created
configmap/argo-events-controller-config created
deployment.apps/controller-manager created

https://github.com/Cloud-Linuxer/Argo-test/blob/main/Argo-EventsBus.yaml

이벤트 버스는 Argo-Event 를 하면서 가장 인상적인 아키텍처였다.

k apply -f Argo-EventsBus.yaml 
eventbus.argoproj.io/default created

이유는 이렇다.

 k get pod
NAME                                  READY   STATUS    RESTARTS   AGE
argo-server-5779fd7868-nb77l          0/1     Running   0          25m
controller-manager-78bbd4559b-sd28w   1/1     Running   0          3m53s
eventbus-default-stan-0               2/2     Running   0          72s
eventbus-default-stan-1               2/2     Running   0          63s
eventbus-default-stan-2               2/2     Running   0          54s
workflow-controller-5f7f4d8-96bnm     1/1     Running   0          25m

세개의 이벤트 버스가 pod 로 뜨고,

https://argoproj.github.io/argo-events/concepts/architecture/

event source와 sonser 사이에서 버스역할을 하는 pod 가 있는것이었다.

여기까지 왔다면, 이제 Argo-WorkFlow/Events 를 사용할 준비가 완료된것이다.

그럼 한번 Ingress 를 배포해보자

https://github.com/Cloud-Linuxer/Argo-test/blob/main/Argo-Server-Ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argo-ingress
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}]'
    alb.ingress.kubernetes.io/security-groups: sg-0cd215a1ea38d94bf
    alb.ingress.kubernetes.io/subnets: subnet-0b00bab5bde81c736,subnet-0928ee0c6eaaecea2
    alb.ingress.kubernetes.io/backend-protocol: HTTP
    alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
    alb.ingress.kubernetes.io/healthcheck-path: /
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: argo-server
              port:
                number: 2746

어차피 보안그룹 서브넷만 수정해서 넣자. 바로된다. 만약안되면 pod가 존재하는 node의 보안그룹에 2746포트를 열지않아서 그렇다. 열어주자.

그러면 꼴뚜기 친구를 볼수있다. 이제 WorkFlow UI 까지 띄우고 Events 를 사용할 준비가 마무리 된거다.

git webhook을 이용한 간단한 테스트 정도만 이어 갈거다 걱정하지 마라. 먼저 알아야 할것은 workflow / Events 라는 놈은 CRD를 떡칠해 놨기에 우리가 생각하는 K8S의 컴포넌트 동작과는 다르다. K8S의 컴포넌트를 이용하긴 하나, 받아서 던져주는 EventBus 같은녀석도 있기때문에 Ingress 가 정상적으로 동작해도 Bus를 탈수없는 경우도 있다.

그럼 Events 로 가기전에 CRD의 RBAC를 설치해야 한다.

 # sensor rbac
k apply -f https://raw.githubusercontent.com/argoproj/argo-events/master/examples/rbac/sensor-rbac.yaml
 # workflow rbac
k apply -f https://raw.githubusercontent.com/argoproj/argo-events/master/examples/rbac/workflow-rbac.yaml

나는 이 RBAC를 적용하면서 사실 살짝 현타가 왔다. CRD의 모든 동작을 알순없더라도 적어도 내가 통제할수는 있는 레벨이어야 하는데 너무 쪼개진 컴포넌트 들이 나를 힘들게 했다.

자 그럼 이제 이벤트소스-웹훅-센서-트리거 를 배포해 보자.

사실 엄청 거창해 보이지만 yaml 로는 두개다.

https://github.com/Cloud-Linuxer/Argo-test/blob/main/Argo-EventSource.yaml

apiVersion: argoproj.io/v1alpha1
kind: EventSource
metadata:
  name: webhook
spec:
  service:
    ports:
      - port: 12000
        targetPort: 12000
  webhook:
    example:
      port: "12000"
      endpoint: /
      method: POST

EventSource 의 yaml 은 하나지만 CRD라 Service 와 Pod를 배포해준다.

 k get all -l eventsource-name=webhook
NAME                                             READY   STATUS    RESTARTS   AGE
pod/webhook-eventsource-r7x58-8575c749bb-fsjnf   1/1     Running   0          6m

NAME                              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)     AGE
service/webhook-eventsource-svc   ClusterIP   100.64.116.226   <none>        12000/TCP   6m

k get eventsources.argoproj.io 
NAME      AGE
webhook   10m

eventsource-name=webhook label 이 붙는다. owner나 이런 저런것도 붙는다.

그럼 이제 Sonser를 배포할거다. 이벤트소스를 통해 전달받은 웹훅을 센서가 받아서 트리거를 호출하고 실행한다.

https://github.com/Cloud-Linuxer/Argo-test/blob/main/Argo-Sensor-Webhook.yaml

k apply -f Argo-Sensor-Webhook.yaml 
sensor.argoproj.io/webhook created

배포가 완료되면

이렇게 Argo WorkFlow UI에서 확인할수 있다.
그럼 웹훅까지 발생시켜 보자.

웹훅도 Ingress 로 받을 거다.

k get svc
NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
argo-server                 ClusterIP   100.68.95.174    <none>        2746/TCP                     37m
eventbus-default-stan-svc   ClusterIP   None             <none>        4222/TCP,6222/TCP,8222/TCP   64m
webhook-eventsource-svc     ClusterIP   100.64.116.226   <none>        12000/TCP                    14m

Service를 보면 webhook-eventsource-svc Eventsource 가 있다. 이걸 Ingress 로 연결해야한다. Ingress 를 생성하면 이런식으로 두개의 Ingress 가 생긴다.

k get ingress
NAME                       CLASS   HOSTS   ADDRESS                                                                    PORTS   AGE
argo-eventsource-ingress   alb     *       k8s-argo-argoeven-44fe46d880-57919429.ap-northeast-2.elb.amazonaws.com     80      26s
argo-ingress               alb     *       k8s-argo-argoingr-17062136f1-1802335500.ap-northeast-2.elb.amazonaws.com   80      44m

그럼 argo-eventsource-ingress 쪽으로 웹훅을 날려보자.

curl -d '{"message":"this is my first webhook"}' -H "Content-Type: application/json" -X POST http://k8s-argo-argoeven-44fe46d880-57919429.ap-northeast-2.elb.amazonaws.com
success

success가 떨어질것이다. 그럼 정상적으로 실행됬는지 UI에서 확인해보자.

WorkFlow가 생성된게 보인다. 그럼 이걸 CLI 에서도 확인해보자.
k get wf
NAME            STATUS      AGE   MESSAGE
webhook-9vzcz   Succeeded   88s   

정상적으로 완료됬다. 그럼 대량의 웹훅을 날린다면???

헤헤 주거라 WorkFlow!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

대량으로 생성된걸 확인할수 있다. 이때 pod는?

k get pod | grep webhook
webhook-4j9gq                                0/2     Completed   0          108s
webhook-4q646                                0/2     Completed   0          101s
webhook-6k44h                                0/2     Completed   0          96s
webhook-96w4x                                0/2     Completed   0          106s
webhook-9vzcz                                0/2     Completed   0          3m58s
webhook-blmsq                                0/2     Completed   0          107s
webhook-eventsource-r7x58-8575c749bb-fsjnf   1/1     Running     0          26m
webhook-fq6d5                                0/2     Completed   0          102s
webhook-fzh2t                                0/2     Completed   0          103s
webhook-g58r9                                0/2     Completed   0          103s
webhook-gk9wb                                0/2     Completed   0          98s
webhook-mh6b2                                0/2     Completed   0          104s
webhook-mm9qx                                0/2     Completed   0          105s
webhook-n9x4k                                0/2     Completed   0          106s
webhook-nhd8l                                0/2     Completed   0          109s
webhook-ps8z6                                0/2     Completed   0          109s
webhook-qnnbd                                0/2     Completed   0          100s
webhook-qrm8d                                0/2     Completed   0          97s
webhook-rcztl                                0/2     Completed   0          98s
webhook-sensor-lqv7w-6459d75dbb-xlkh8        1/1     Running     0          13m
webhook-vs2tm                                0/2     Completed   0          99s
webhook-xtfbh                                0/2     Completed   0          104s
webhook-z6twq                                0/2     Completed   0          108s

늘어난다.

나는 이다음 github webhook과 인증인가 Ingress 보호등 다양한 부분을 확인하고 테스트했다. 그이후엔 셀프로 이걸 관리하면서 사용할거라면 안하는게 맞다는 결론을 내렸다.

여러분도 Workflow를 적용하려 한다면 고충이 클것이다.

이포스팅이 여러분의 앞날에 삽질을 줄여주길 바란다. 이만!

PKOS-kOps-2Week

ㅠㅠ 울고 시작하려한다. 스터디에 집중을 하려고 한다.
가시다님 그동안 숙제 너무 조금해서 죄송했어요...ㅠㅠ엉엉흑흑

일단 사과를 드리고 시작하며, 이제 살짝 각잡고 kOps 부터 설명하겠다.

kOps는 Kubernetes Operations의 약자로, Kubernetes 클러스터를 AWS (Amazon Web Services)에서 손쉽게 설치, 업그레이드 및 관리할 수 있도록 해주는 오픈 소스 도구이다. Kops를 사용하면 CLI(Command Line Interface)를 통해 클러스터를 구성할 수 있으며, YAML 파일을 사용하여 쉽게 클러스터를 정의할 수 있다

Kops는 여러 가지 기능을 제공한다

  1. 클러스터 구성: Kops를 사용하여 Kubernetes 클러스터를 쉽게 구성할 수 있다. YAML 파일을 사용하여 클러스터 구성을 정의하고, AWS 리소스를 프로비저닝하고 구성을 배포한다.
  2. 노드 그룹: Kops는 노드 그룹을 사용하여 클러스터 내에서 다양한 유형의 노드를 정의할 수 있다. 예를 들어, CPU 또는 메모리 요구 사항이 높은 애플리케이션을 실행하는 데 필요한 노드 그룹을 만들 수 있다.
  3. 클러스터 업그레이드: Kops를 사용하여 클러스터를 업그레이드하면, 기존 클러스터의 구성 및 애플리케이션 상태가 유지된다. 이는 클러스터 업그레이드가 더욱 안정적이며 안전하게 진행될 수 있도록 도와준다.
  4. 롤링 업데이트: Kops는 클러스터의 노드 그룹을 업데이트할 때 롤링 업데이트를 수행할 수 있다. 이를 통해 클러스터에 대한 서비스 중단 없이 노드 그룹의 업데이트를 진행할 수 있다.

Kops는 쉽게 시작할 수 있는 Kubernetes 설치 및 관리 도구 중 하나이다, AWS에서 Kubernetes 클러스터를 운영하는 데 매우 유용하다.

PKOS에서는 24단계 실습으로 정복하는 쿠버네티스 로 실습을 진행하면서 kOps를 사용한다.

나는 EKS 를 근래에 주로 다루고 있다.

kOps 와 EKS를 간략하게 비교해봤다.

기능 / 속성kOpsEKS
관리 형태오픈 소스 도구완전 관리형 서비스
클라우드 플랫폼AWS, GCP 등 다양한 플랫폼AWS 전용
클러스터 구축사용자 정의 구성 가능표준화된 구성 사용
클러스터 업그레이드사용자가 직접 관리AWS가 제공하는 관리형 업그레이드
클러스터 유효성 검사kOps 도구를 사용하여 제공AWS 콘솔 및 API를 통해 제공
비용인프라 리소스 비용만 발생인프라 리소스 및 EKS 서비스 비용
운영의 편의성사용자가 더 많은 관리를 수행함AWS가 더 많은 관리를 처리함

역시 관리형이 편하다.

이번주에는 K8S의 네트워킹에 대해서 공부를 했는데 다른점이 많은 kOps 와 EKS지만 kOps 를 사용하면 EKS를 배우기 편한 부분이 있다. 이유는 에드온이나, CNI를 같은것을 사용할수 있다.

awsLoadBalancerController / CNI로는 amazonvpc 를 사용한다.

내가 이야기할 것은 CNI다.

amazonvpc CNI 같은 경우에는 한가지 특징이 있는데 AWS ENI를 컨테이너에 연결하여 일반적으로 우리가 사용하는 kube-proxy의 동작이 현저하게 줄어들게 된다.

kube-proxy의 동작이 줄어드는 아키텍처는 노드에서의 네트워크 처리횟수가 줄어들어 CPU의 사용량이 줄어든다. 기본적으로 리눅스 네트워크 스택은 자원의 사용량이 적지만 네트워크의 미학을 가진 K8S는 적극적으로 리눅스네트워크 스택을 사용한다. 그러므로 노드의 부하는 커진다. 이런 문제를 amazonvpc CNI는 회피할수 있는 방법을 제시한것이다.

POD가 클러스터를 통하지 않고 통신하는 방식은 Network Hop을 줄이기 때문에 일반적인 오버레이 네트워크의 Network Hop보다 현저하게 줄어들고 빠른 방식이 가능한것이다.

이때문에 kube-proxy를 쓰는 nodeport 같은 형태의 Sevice는 EKS에 어울리지 않는다.

반드시 awsLoadBalancerController 를 사용할떈 target option을 IP로 사용하길 추천한다.

pod graceful shutdown

    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
          resources:
            limits:
              cpu: 500m
            requests:
              cpu: 200m
          lifecycle:
            preStop:
              exec:
                command: ["/bin/sleep", "30"]

.

.

hpa 발생시 pod의 갑작스런 종료로 pod에 연결된 사용자가 502를 받게된다.

모든 리퀘스트를 처리 후에 종료되도록 30초간의 유예를 준다 설정 변경 lifecycle preStop 를 이용하여 우아한 종료를!

PKOS-kOps-1Week

이번에 스터디에 참가하게 되었다.

가시다님의 PKOS!

스터디할시에 사용하는 책은 24단계 실습으로 정복하는 쿠버네티스 이다.

kOps를 프로비저닝하는데 오타가 발생해서 심심해서 스크립트를 만들었다.
그덕에 한번 다시 만들었다.

#!/bin/bash

echo "클러스터명-도메인을 입력해주세요 : "
read KOPS_CLUSTER_NAME
echo "버킷명을 입력해 주세요 s3:// 는 입력하지 않아도 됩니다. : "
read  KOPS_STATE_STORE
# Access Key를 입력 받음
read -p "엑세스키를 입력해주세요 : " ACCESS_KEY

# Secret Access Key를 입력 받음
read -p "시크릿키를 입력해주세요 : " SECRET_KEY

# AWS 계정 구성
aws configure set aws_access_key_id $ACCESS_KEY
aws configure set aws_secret_access_key $SECRET_KEY
echo 'export AWS_PAGER=""' >>~/.bashrc
echo "export REGION=ap-northeast-2" >>~/.bashrc
echo "export KOPS_CLUSTER_NAME=$KOPS_CLUSTER_NAME" >>~/.bashrc
echo "export KOPS_STATE_STORE=s3://$KOPS_STATE_STORE" >>~/.bashrc

kops create cluster --zones="$REGION"a,"$REGION"c --networking amazonvpc --cloud aws \
--master-size t3.medium --node-size t3.medium --node-count=2 --network-cidr 172.30.0.0/16 \
--ssh-public-key ~/.ssh/id_rsa.pub --name=$KOPS_CLUSTER_NAME --kubernetes-version "1.24.10" --dry-run -o yaml > mykops.yaml


kops create cluster --zones="$REGION"a,"$REGION"c --networking amazonvpc --cloud aws \
--master-size t3.medium --node-size t3.medium --node-count=2 --network-cidr 172.30.0.0/16 \
--ssh-public-key ~/.ssh/id_rsa.pub --name=$KOPS_CLUSTER_NAME --kubernetes-version "1.24.10" -y

source <(kubectl completion bash)
echo 'source <(kubectl completion bash)' >> ~/.bashrc
echo 'alias k=kubectl' >> ~/.bashrc
echo 'complete -F __start_kubectl k' >> ~/.bashrc

read 명령어를 이용하여 스크립트에 변수를 부여하고 입력받은 변수를 이용하여 aws configure 를 설정하고, kops 명령어로 k8s 클러스터를 프로비저닝한다.

이거다음에는 사실 initscript 에 내가원하는 값을 넣는게 제일 편하나 그건..좀 공개하기 애매하니 스크립트라도 공개한다.