Filebeat Lightweight shipper for logs from k8s to Elasticsearch

Beat

สวัสดีครับ DevOps 101 ของเรา วันนี้ จะมาพูดถึง Filebeat นะครับ ..

Filebeat คืออะไร?
Filebeat = Lightweight shipper for logs
“Whether you’re collecting from security devices, cloud, containers, hosts, or OT, Filebeat helps you keep the simple things simple by offering a lightweight way to forward and centralize logs and files.”

ถ้าเอาแบบเข้าใจง่ายๆ ก็คือ ตัวกวาด logs จากที่ต่างๆ เข้ามาที่ centralize logs ในที่นี้ ผมจะพูดถึง k8s cluster (EKS) logs ไปเก็บที่ Elasticsearch ละกันนะครับ ..

จริงๆ ยังมี ตัวอื่นๆ อีก นะครับ ที่ทำงานคล้ายๆ Filebeat เช่น Fluentd, Fluentbit

ในเมื่อเราใช้ ELK Stack ใน Ecosystem ของเราแล้ว การที่เราอยาก search logs ต่างๆ ที่เกิดจาก container ของเรา ได้ง่ายสุด ก็คือการ ship logs จาก k8s cluster ของเรา ไปเก็บไว้บน Elasticsearch แล้วทำการ search ผ่าน Kibana ..

วิธีการ Install Filebeat ใน k8s cluster

ทำได้หลายวิธีครับ ในที่นี้ ผมจะใช้วิธีง่ายๆ ผ่าน kubectl ดังต่อไปนี้

1. Create Secret โดยใส่ค่าที่จำเป็น พวกนี้ลงไป

ELASTICSEARCH_HOST = Endpoint ของ Elasticsearch เรา
ELASTICSEARCH_PORT = Port ที่ Elasticsearch เราทำงานอยู่
ELASTICSEARCH_USERNAME = Username ของ Elasticsearch
ELASTICSEARCH_PASSWORD = Password ของ Elasticsearch
ELASTIC_CLOUD_ID = Cloud ID ในกรณีที่เราใช้ผ่าน Cloud Service ของ Elastic.co
ELASTIC_CLOUD_AUTH = Username:Password ของ Elasticsearch

filebeat-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: filebeat
  namespace: kube-system
type: Opaque
data:
  ELASTICSEARCH_HOST: aHR0cDovL2xvY2FsaG9zdA==
  ELASTICSEARCH_PASSWORD: 
  ELASTICSEARCH_PORT: OTIwMA==
  ELASTICSEARCH_USERNAME: 
  ELASTIC_CLOUD_AUTH: 
  ELASTIC_CLOUD_ID: 

จากนั้น สั่ง create secret

kubectl create -f filebeat-secret.yaml

2. Create Deployment และ Resource อื่นๆ

filebeat-kubernetes.yaml

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-config
  namespace: kube-system
  labels:
    k8s-app: filebeat
data:
  filebeat.yml: |-
    # To enable hints based autodiscover, remove `filebeat.inputs` configuration and uncomment this:
    filebeat.autodiscover:
      providers:
       - type: kubernetes
         node: ${NODE_NAME}
         hints.enabled: true
         hints.default_config:
           type: container
           paths:
             - /var/log/containers/*${data.kubernetes.container.id}.log

    # Filter by container.name
    # filebeat.autodiscover:
    #   providers:
    #     - type: kubernetes
    #       node: ${NODE_NAME}
    #       templates:
    #         - condition:
    #             contains:
    #               kubernetes.container.name: "container01"
    #           config:
    #             - type: container
    #               paths:
    #                 - "/var/log/containers/*-${data.kubernetes.container.id}.log"
    #         - condition:
    #             contains:
    #               kubernetes.container.name: "container02"
    #           config:
    #             - type: container
    #               paths:
    #                 - "/var/log/containers/*-${data.kubernetes.container.id}.log"

    processors:
      - add_cloud_metadata:
      - add_host_metadata:

    cloud.id: ${ELASTIC_CLOUD_ID}
    cloud.auth: ${ELASTIC_CLOUD_AUTH}

    output.elasticsearch:
      hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}']
      #index: "%{[fields.my_type]}-%{[agent.version]}-%{+yyyy.MM.dd}" 
      username: ${ELASTICSEARCH_USERNAME}
      password: ${ELASTICSEARCH_PASSWORD}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: filebeat
  namespace: kube-system
  labels:
    k8s-app: filebeat
spec:
  selector:
    matchLabels:
      k8s-app: filebeat
  template:
    metadata:
      labels:
        k8s-app: filebeat
    spec:
      serviceAccountName: filebeat
      terminationGracePeriodSeconds: 30
      hostNetwork: true
      dnsPolicy: ClusterFirstWithHostNet
      containers:
        - name: filebeat
          image: docker.elastic.co/beats/filebeat:8.6.2
          args: ["-c", "/etc/filebeat.yml", "-e"]
          env:
            - name: ELASTICSEARCH_HOST
              valueFrom:
                secretKeyRef:
                  name: filebeat
                  key: ELASTICSEARCH_HOST
            - name: ELASTICSEARCH_PORT
              valueFrom:
                secretKeyRef:
                  name: filebeat
                  key: ELASTICSEARCH_PORT
            - name: ELASTICSEARCH_USERNAME
              valueFrom:
                secretKeyRef:
                  name: filebeat
                  key: ELASTICSEARCH_USERNAME
            - name: ELASTICSEARCH_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: filebeat
                  key: ELASTICSEARCH_PASSWORD
            - name: ELASTIC_CLOUD_ID
              valueFrom:
                secretKeyRef:
                  name: filebeat
                  key: ELASTIC_CLOUD_ID
            - name: ELASTIC_CLOUD_AUTH
              valueFrom:
                secretKeyRef:
                  name: filebeat
                  key: ELASTIC_CLOUD_AUTH
            - name: NODE_NAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
          securityContext:
            runAsUser: 0
            # If using Red Hat OpenShift uncomment this:
            #privileged: true
          resources:
            limits:
              memory: 200Mi
            requests:
              cpu: 100m
              memory: 100Mi
          volumeMounts:
            - name: config
              mountPath: /etc/filebeat.yml
              readOnly: true
              subPath: filebeat.yml
            - name: data
              mountPath: /usr/share/filebeat/data
            - name: varlibdockercontainers
              mountPath: /var/lib/docker/containers
              readOnly: true
            - name: varlog
              mountPath: /var/log
              readOnly: true
      volumes:
        - name: config
          configMap:
            defaultMode: 0640
            name: filebeat-config
        - name: varlibdockercontainers
          hostPath:
            path: /var/lib/docker/containers
        - name: varlog
          hostPath:
            path: /var/log
        # data folder stores a registry of read status for all files, so we don't send everything again on a Filebeat pod restart
        - name: data
          hostPath:
            # When filebeat runs as non-root user, this directory needs to be writable by group (g+w).
            path: /var/lib/filebeat-data
            type: DirectoryOrCreate
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: filebeat
subjects:
  - kind: ServiceAccount
    name: filebeat
    namespace: kube-system
roleRef:
  kind: ClusterRole
  name: filebeat
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: filebeat
  namespace: kube-system
subjects:
  - kind: ServiceAccount
    name: filebeat
    namespace: kube-system
roleRef:
  kind: Role
  name: filebeat
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: filebeat-kubeadm-config
  namespace: kube-system
subjects:
  - kind: ServiceAccount
    name: filebeat
    namespace: kube-system
roleRef:
  kind: Role
  name: filebeat-kubeadm-config
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: filebeat
  labels:
    k8s-app: filebeat
rules:
  - apiGroups: [""] # "" indicates the core API group
    resources:
      - namespaces
      - pods
      - nodes
    verbs:
      - get
      - watch
      - list
  - apiGroups: ["apps"]
    resources:
      - replicasets
    verbs: ["get", "list", "watch"]
  - apiGroups: ["batch"]
    resources:
      - jobs
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: filebeat
  # should be the namespace where filebeat is running
  namespace: kube-system
  labels:
    k8s-app: filebeat
rules:
  - apiGroups:
      - coordination.k8s.io
    resources:
      - leases
    verbs: ["get", "create", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: filebeat-kubeadm-config
  namespace: kube-system
  labels:
    k8s-app: filebeat
rules:
  - apiGroups: [""]
    resources:
      - configmaps
    resourceNames:
      - kubeadm-config
    verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: filebeat
  namespace: kube-system
  labels:
    k8s-app: filebeat
---
 

จากนั้น สั่ง create deployment

kubectl create -f filebeat-kubernetes.yaml

3. Search k8s cluster logs ผ่าน Kibana

ถ้า config ทุกอย่างเราถูกต้อง container ทำงานได้ เราก็จะได้ logs ของ k8s cluster เรา ไปเก็บบน Elasticsearch และทำการ search ผ่าน Kibana ได้เลย

Kibana Search

* เราสามารถ filter input ของ Logs ที่จะ ship ไปเก็บ ที่ Elasticsearch ได้

ตัวอย่างอยู่ใน filebeat-kubernetes.yaml ที่ comment ไว้

เป็นอย่างไรกันบ้างครับ ไม่ยากเลยใช่ไหมครับ สำหรับการ ship logs จาก k8s cluster ของเรา ไปเก็บบน Elasticsearch 🙂

Git Repo: https://github.com/pornpasok/k8s-logs-es-filebeat
Ref: https://www.elastic.co/beats/filebeat

ลองใช้ Argo CD deploy application บน EKS

Argo CD Dashboard
Argo CD Dashboard

DevOps 101 ของเราวันนี้ จะมาทดลองใช้งาน Argo CD กันนะครับ .. ว่ามันดียังไง ทำอะไรได้บ้าง และเหมาะกับใคร? Logo ของ Argo CD ก็น่ารักดีครับ เป็นรูป มนุษย์ต่างดาว หรือ หมึก ก็ไม่รู้ ..

นิยามที่ทาง Argo CD เค้าบอกไว้ ในเว็บเค้าเองก็คือ ..

What Is Argo CD?
“Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.”

ถ้าสรุปให้เข้าใจได้ง่ายๆ ก็คือ เป็น Tools สำหรับทำ CD (Continuous Delivery) ที่ตรงไปตรงมา
ไม่ซับซ้อน สำหรับ deploy Application บน k8s ด้วยการใช้หลักการของ GitOps

รายละเอียดเพิ่มเติม : https://argo-cd.readthedocs.io/

เท่าที่ลองเล่นดู หลังจากที่เรามี k8s cluster แล้ว (ในที่นี่ผมใช้ EKS) เราก็จะต้อง Install เจ้า Argo CD ใน k8s cluster ของเรา จากนั้น เราก็จะใช้ความสามารถของ Argo CD ได้ ด้วยการผูกกับ Git Repository ที่ใช้ในการ deploy Application ของเรา เท่านี้ก็เป็นอันเรียบร้อยครับ .. เมื่อเรามีการเปลี่ยนแปลง configuration บน git เจ้า Argo CD ก็จะมา sync config ไป deploy บน k8s cluster ให้เรา ..

ดูรายละเอียดเพิ่มเติมที่ YouTube ของ Nana ได้ที่นี่ครับ : https://www.youtube.com/watch?v=MeU5_k9ssrs

สรุปความคิดเห็นส่วนตัว ที่ลองใช้งาน (ยังไม่ได้ใช้จริงๆ จังๆ บน Production)

ข้อดี
– Install ง่ายมาก ไม่เจอปัญหาอะไรเลย ใช้ resource น้อยมาก
– ไม่ต้องวุ่นวาย เรื่องการ Install kubectl เพราะอยู่ใน k8s cluster อยู่แล้ว
– ไม่ต้องวุ่นวาย เรื่องการจัดการ Credentials ในการเข้าถึง k8s cluster
– มี Dashboard ที่แสดงรายละเอียด ของการ deploy Application ได้ละเอียด ครบถ้วน
– Sync manifest จาก Git Repository ได้รวดเร็ว
– หน้าตาดูดี สวยงาม

ข้อเสีย
– Deploy (CD) บน k8s cluster ได้เท่านั้น
– ในส่วนของ CI (Continuous Integration) ยังต้องใช้ 3rd-party อื่นช่วย ไม่ว่าจะเป็น GitHub Action, GitLab CI, Jenkins
– ถ้าดูพวก Metrics ได้ด้วย น่าจะดีเลย แต่คิดว่า คงออกแบบมา ให้ simple ทำงาน CD ได้อย่างดี ก็พอ

Lens The Kubernetes IDE + Grafana Dashboard

Lens The Kubernetes IDE

สวัสดีครับ DevOps 101 ของเราวันนี้ นำเสนอ Lens ครับ .. ตอนนี้ ก็ออกมาถึง version 5.x.x กันแล้ว ณ ตอนที่ผมเขียน blog ก็เป็น version 5.1.3 เพื่อนๆ บางท่าน อาจจะเคยใช้งานกันมาบ้างแล้ว .. แต่สำหรับบางท่านที่ยังไม่เคยใช้งาน อาจจะยังสงสัยว่ามันคืออะไรกัน เจ้า Lens .. จากคำอธิบายในเว็บของเค้าคือ ..

“Lens is the only IDE you’ll ever need to take control of your Kubernetes clusters. It’s built on open source and free.”

สรุปสั้นๆ เข้าใจง่ายๆ ก็คือ Lens เป็น IDE ที่ช่วยจัดการ Kubernetes (k8s) cluster ของเรา เป็น Open Source และ Free 🙂
สำหรับท่านที่เคยใช้ kube-proxy ที่เป็น Dashboard ของ k8s เอง .. จะพบว่า มันใช้งานไม่ค่อยสะดวกเท่าไรนัก .. ลองเปลี่ยนมาใช้ Lens ดูครับ จะพบว่าสะดวกกว่ามากๆ ..

สำหรับวิธีการติดตั้ง Lens ก็ไป download ได้เลยครับที่ https://k8slens.dev/ มีทั้งบน Mac OS, Windows และ Linux ครับ .. ตัว Lens เองจะใช้ file config เดียวกับ kubectl ของเราคือจะอยู่ที่ ~/.kube/config ซึ่งถ้าใครใช้งาน kubectl ได้อยู่แล้ว ก็จะไม่มีปัญหา อะไร .. แต่ถ้าเปิด Lens ขึ้นมาแล้ว ยังใช้งานไม่ได้ ก็ให้ไปลองดูที่ ~/.kube/config ว่ามีค่า config ต่างๆ ถูกต้องไหม .. หรือถ้าใครใช้ EKS อยู่ วิธีการง่ายๆ ก็คือ การสั่ง update kube config ครับ ดังตัวอย่าง ..

aws eks update-kubeconfig --name tono-eks \
--region ap-southeast-1 \
--profile tono-admin

สิ่งที่อยากจะนำเสนอเพิ่มเติม สำหรับเจ้า Lens ก็คือ Lens Metrics ซึ่งตรงนี้ จะทำให้เราดู resource ของ k8s cluster เราได้ง่ายขึ้น สะดวกขึ้นครับ .. จริงๆ แล้ว ก็คือการติดตั้ง Prometheus + Kube State Metrics + node exporter เข้าไป เพื่อเก็บ metrics ต่างๆ จาก k8s cluster เราลงบน Prometheus นั่นเองครับ .. มาดูวิธีการ enable ตรงนี้กันครับ ..

1.คลิกขวาที่ icon ของ k8s cluster ของเรา แล้วเลือก Settings

คลิกขวา ที่ icon k8s cluster แล้วเลือก Settings

2.มาที่ Lens Metrics แล้วทำการ Enable PROMETHEUS, KUBE STATE METRICS, NODE EXPORTER จากนั้นกด Apply

Lens Metrics กด Enable ทั้ง 3 อัน

3.กลับมาที่หน้าหลักของ Lens ไปที่ Workloads > Pods ก็จะเห็นว่า pods ต่างๆ ที่เกี่ยวข้องกับ Lens Metrics ของเราเขียวแล้ว

Pods ที่เกี่ยวกับ Lens Metrics เขียวแล้ว

4.กดไปที่ Cluster หรือ Nods ก็จะเห็น Metrics ต่างๆ แสดงผลแล้วครับ

แสดง Metrics ของ k8s cluster ได้แล้ว

ขั้นตอนต่างๆ ก็ง่ายๆ ประมาณนี้ครับ เราก็จะได้ Lens Metrics ที่เป็น Dashboard & Monitoring สำหรับ ดู รายละเอียดต่างๆ ของ k8s cluster ของเรากันแล้วครับ ..

Update!!! (2021-09-25) Grafana Dashboard

วันนี้ มา update การทำ Dashboad & Monitoring ของ k8s cluster ที่จะดูได้ละเอียดกว่านี้ ด้วย Grafana ครับ ..

หลายๆ ท่าน คงอยากมี dashboard (Grafana) เอาไว้ดู metrics ต่างๆ ของ k8s cluster ของเรา ให้คนในทีมได้เอาไว้ดู ในทุกที่ ทุกเวลา .. ซึ่งเราก็สามารถติดตั้งได้ผ่าน Lens เลยครับ โดยมีขั้นตอน เพิ่มเติมดังนี้ ..

1.ไปที่ Apps > Charts แล้ว search “prometheus-operator”

prometheus-operator

2.กด install ใน namespace ที่เราต้องการ ในที่นี้ผม create ns ชื่อ prometheus มาเพิ่มเติม

หรือถ้าอยากลอง install เอง ก็สามารถทำตามขั้นตอน ของ prometheus-operator ได้ตามนี้เลยครับ ..
[Link] https://github.com/prometheus-operator/prometheus-operator

3.ไปที่ Network > Services จะพบ service ที่ชื่อ “prometheus-operator-xxx-grafana”

prometheus-operator-grafana

4.ทำการ login เข้า Grafana โดย default user-password สามารถดูได้ที่ Configuration > Secrets เลือกดู secret “prometheus-operator-xxx-grafana”

prometheus-operator-grafana-password

5.ไปที่ Dashboard จะเห็นว่า มี k8s cluster dashboard ที่จำเป็นมาให้เราเรียบร้อย

Grafana k8s Dashboard & Monitoring

เป็นอย่างไรกันบ้างครับ ไม่ยากเลยใช่ไหมครับ? แต่การที่เราจะ expose Grafana dashboard ของเรา ให้คนอื่น สามารถเข้ามาได้นั้น เราต้องมี ingress มาต่อ กับ service grafana ของเราด้วยนะครับ .. ในครั้งต่อไป ผมจะมาพูดถึงการสร้าง ingress ให้กับ k8s cluster ของเรากันครับ .. 🙂

มาต่อกันครับ ในขั้นตอนการทำให้ Grafana ของเรา สามารถเข้าจากที่ไหน ก็ได้

6. สร้าง Ingress ให้กับ Grafana เรา ให้สามารถเข้าดูจาก public ได้

ในที่นี้ ผมจะ ทำการ create ingress ให้กับ Grafana ของเรากันครับ ด้วย manifest (YAML) ประมาณนี้

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: grafana
  namespace: prometheus
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: grafana.domain.com
      http:
        paths:
          - backend:
              serviceName: prometheus-operator-xxx-grafana
              servicePort: 80

7. ทำการ Add CNAME record ของ Grafana มาที่ Ingress Endpoint ของเรา

อย่างในที่นี้ ผมใช้บริการ DNS ของ CloudFlare อยู่ ผมก็จะไป Add เพิ่ม ประมาณนี้ครับ

CloudFlare DNS
CloudFlare DNS

เพียงเท่านี้ เราก็จะสามารถเรียกใช้งาน URL ของ Grafana จากที่ไหน ก็ได้แล้วครับ ..

ออกแบบ DevOps Architecture CI/CD Pipeline ให้เหมาะกับงาน และองค์กร

DevOps Architecture CI/CD Pipeline

สวัสดีครับ .. DevOps 101 ของเรา วันนี้มีโจทย์ มาอันนึงครับ ให้ออกแบบ Architecture, Tech Stack และ CI/CD Pipeline ของ Application ที่มีคนใช้งานจำนวนมาก app นึง ให้กับองค์กร ขนาดใหญ่ ระดับพนักงาน 200,000 คน ++ ..

จริงๆ ในการออกแบบ ไม่มีอะไรถูกอะไรผิดครับ .. หลักการง่ายๆ ก็คือ “Simply the best” .. ทำให้ deploy ง่ายๆ .. รองรับ load สูงๆ ให้ได้ .. มีระบบ Monitoring ที่ดี .. และเหมาะสม กับงานและองค์กร ..

เนื่องจาก ทางองค์กร มี Single Sign-On อยู่แล้ว ซึ่งสามารถใช้งานผ่าน AWS Cognito ได้ .. เราก็เลยสามารถ ใช้งานได้เลย และเอาไปต่อกับ CI/CD Tools ที่จำเป็นของเราได้ ไม่ว่าจะเป็น GitLab, Jenkins, Nexus Repository และอื่นๆ ในอนาคต ..

ในที่นี้ ตัว Application เราเลือกพัฒนาโดยใช้ Next.js เพราะว่า ต้องรองรับ user ที่เข้าใช้งานหลากหลาย ไม่ว่าจะเป็น บน Desktop และ Mobile .. และทางทีม Developer มีความเชี่ยวชาญในส่วนของ Next.js อยู่แล้ว .. ในส่วนของ CI/CD Tools เราเลือกใช้ Jenkins และทำ CI/CD Pipeline เป็น Jenkinsfile (Declarative Pipeline) แบบง่ายๆ stage ตรงไปตรงมา ใครมาอ่าน ก็เข้าใจ .. เพราะว่าอนาคต เราอยากเอา template นี้ ไป reuse ให้ทีมอื่น ในองค์กร เราได้ใช้ตามด้วย ..

ในส่วนของ Artifactory ที่ใช้เก็บ Docker Images และ binary files ต่างๆ เราเลือกใช้ Nexus Repository เป็น private repository ของเรา .. ส่วน SCM (Source Code Management) อันนี้จริงๆ เราคิดว่า เป็นอะไรก็ได้ ไม่ว่าจะ github, gitlab, ecr, bitbucket .. แต่องค์กรเรามี GitLab อยู่แล้ว ก็เลยใช้ตัวนี้ไปเลย .. ส่วนของ static code scan เราเลือกใช้ SonarQube แต่สิ่งที่เราอยากดูจริงๆ ก็เป็นส่วนของ code coverage มากกว่า ..

ในส่วนของ Server ที่เราจะใช้ในการ deploy ตัว Application ของเราขึ้นไป เราเลือกใช้ Amazon EKS (มันคือ k8s cluster บน AWS) เพราะว่าเราไม่ต้องวุ่นวายในการสร้าง k8s cluster ขึ้นมาใช้งานเอง และตัว cost ของ Amazon EKS ก็ไม่ได้แพงกว่า EC2 ธรรมดา เท่าไรนัก ..

ทำไมถึงเลือกใช้ EKS ไม่ใช้ ECS ?

– ผมเองต้องออกตัวไว้ก่อนครับ ว่าความรู้เกี่ยวกับ ECS ของผม แทบจะเป็น 0 .. แต่จากการได้เข้า training กับ AWS ในส่วนของการใช้งาน ECS + DevOps .. ทำให้ผมพอได้รู้บ้างว่า ตัว ECS ทำงานอย่างไร .. เราสามารถ ทำอะไรกับมันได้บ้าง .. ทำให้ผมตัดสินใจได้ทันที ว่างั้นเราไป EKS เถอะ .. เพราะว่า ในการทำ Application ที่รองรับคนใช้งานจำนวนมากนั้น .. การ scale และการ monitoring metrics ต่างๆ ถือว่าเป็นเรื่องสำคัญมาก ซึ่งผมเองคิดว่า EKS ที่เป็น k8s cluster eco system มัน flexible กว่า .. อาจจะเป็นเหตุผลที่เอนเอียงนิดหน่อย จากการที่ผมคุ้นเคยกับ Container Platform ที่เป็น k8s ด้วย .. (k8s, OpenShift)

ในส่วนของ Dashboard & Monitoring Tools ในที่นี้เราเลือกใช้ APM (Application Performance Monitoring) + ELK Stack ในการ monitoring Application ของเรา ที่เป็น Next.js .. ในส่วนของตัว EKS (k8s Cluster) เราเลือกใช้ Lens + Prometheus เป็น manage และ monitoring metrics ต่างๆ .. แต่ตัว Lens เอง มันคือดูแบบ เครื่องใครเครื่องมัน .. อนาคต ถ้าเราอยากทำเป็น dashboard ให้ทั้งทีม ได้ดูผ่านจอ TV LED ร่วมกัน ก็น่าจะเอา Grafana มาทำ dashboard ในส่วนนี้ .. ส่วนตัว Alert Notification เราใช้เป็น webhook ของ MS Teams เพราะว่าทีมเรา และองค์กรเรา ใช้ MS Teams เป็นหลัก ในการทำงานอยู่แล้ว ..

Tech Stack

– Next.js
– GitLab
– Jenkins
– Nexus Repository
– SonarQube
– nginx
– Docker
– Kubernetes (k8s)
– AWS Cognito
– AWS EKS
– Elasticsearch
– Logstash + APM
– Kibana
– Prometheus
– Lens/Grafana
– Microsoft Teams

Jenkins Pipeline Examples

https://github.com/pornpasok/demo-app-k8s

สำหรับท่านใด ที่สนใจ ในการออกแบบ Architecture, Tech Stack และ CI/CD Pipeline ก็สามารถ มา comment พูดคุย แลกเปลี่ยน ปรึกษากันได้ตรงนี้นะครับ .. อย่างที่ผมเน้นย้ำตลอด ไม่มีแบบไหนผิด แบบไหนถูก .. แต่แบบไหนที่เหมาะกับเรา นั่นแหละ คือดีที่สุด ครับ .. 🙂

DevOps 101 Amazon EKS Upgrade node group (instance type)

Amazon EKS

วันนี้มีเรื่องเร่งด่วน เกี่ยวกับ การ scale out Amazon EKS ก็เลยมาเขียนไว้ กันลืม .. และเป็นการแบ่งปันความรู้ เผื่อเพื่อนๆ ท่านอื่น เจอปัญหาแบบผม และต้องการแก้ไข ให้เร็วที่สุด ..

Elastic Kubernetes Service (Amazon EKS) เป็นอีก service นึงบน AWS ที่เป็นที่นิยมใช้งานกัน ทำให้เราไม่ต้องยุ่งยาก ในการสร้าง kubernetes (k8s) cluster เอง .. โดยเราสามารถ create k8s cluster ของเราขึ้นมาใช้ได้ง่ายๆ ดังนี้ ..

0. Create EKS Cluster

eksctl create cluster \
--name tono-eks \
--version 1.19 \
--region ap-southeast-1 \
--nodegroup-name t3-medium \
--node-type t3.medium \
--nodes 3 \
--nodes-min 1 \
--nodes-max 4 \
--ssh-access=true \
--ssh-public-key tono-eks \
--managed --profile tono-admin

0.1 Update kubernetes config

จากนั้น ให้เราทำการ update kubernetes config (~/.kube/config) ด้วยคำสั่ง ..

aws eks --region ap-southeast-1 update-kubeconfig --name tono-eks --profile tono-admin

เพียงเท่านี้ เราก็จะมี k8s cluster ของเราไว้ใช้งานแล้วครับ .. ซึ่งถ้าเรา install เองแบบ k8s hard way จะยุ่งยากมากกกกกก (ก.ไก่ ล้านตัว) +___+

*** เพิ่มเติม –profile tono-admin คือให้ ไปใช้ profile ที่ชื่อ tono-admin ที่เรา config ไว้ใน ~/.aws/credentials

 

แต่เรื่องมันไม่จบเพียงเท่านี้ครับ .. เมื่อเราใช้ไปสักพักนึง EKS Cluster ที่เราสร้างขึ้นมาใช้งาน อาจจะไม่เพียงพอที่จะรองรับ load สูงๆ ได้ .. ที่หน้า console ของ AWS EKS เอง จะมีแค่ให้เลือก เพิ่มจำนวน worker node เท่านั้น ไม่สามารถ แก้ไข instance type เพื่อเพิ่ม spec ได้โดยตรง .. (ทำได้ แต่ต้องไปแก้ Auto Scaling groups ซึ่งยุ่งยาก พอสมควร) แต่เรามีวิธีการใช้ CLI eksctl ในการปรับแต่ง EKS Cluster ของเรา ง่ายๆ ดังนี้ครับ ..

ตัวอย่าง ผมจะเปลี่ยนจากเดิม ที่ใช้ instance type จาก t3.medium เป็น t3.xlarge และ version 1.19 –> 1.20 นะครับ .. ก็จะมี step ดังต่อไปนี้ ..

1. Check EKS node group

eksctl get nodegroups --cluster=tono-eks --profile tono-admin

CLUSTER NODEGROUP STATUS CREATED MIN SIZE MAX SIZE DESIRED CAPACITY INSTANCE TYPE IMAGE ID ASG NAME
tono-eks t3-medium ACTIVE 2021-04-01T04:26:02Z 1 4 3 t3.medium AL2_x86_64 eks-cabc45d7-245e-c62e-ca22-bba57282fd0a

จะเห็นว่า ตอนนี้ spec ของ EKS Cluster เรา มีรายละเอียดดังด้านบน

2. Create new node group

eksctl create nodegroup \
--cluster tono-eks \
--version 1.20 \
--name t3-xlarge \
--node-type t3.xlarge \
--nodes 3 \
--nodes-min 1 \
--nodes-max 4 \
--node-ami auto --profile tono-admin

รอจนเสร็จ จะขึ้น all nodegroups have up-to-date configuration

3. Delete old node group

eksctl delete nodegroup --cluster tono-eks --name t3-medium --profile tono-admin

รอจนเสร็จ จะขึ้น deleted 1 nodegroup(s) from cluster “tono-eks”

eksctl_delete_nodegroup

จากนั้นเราก็จะได้ EKS Cluster เป็น worker node ชุดใหม่ ครับ ดังรูป ..

lens_k8s_monitoring_tools

หรือถ้าไม่มี Lens (k8s monitoring tools) ไว้ดู status ของ EKS Cluster แบบผม ก็สามารถใช้ CLI kubectl ได้ครับ ดังนี้

4. Show EKS nodes

kubectl get node

NAME STATUS ROLES AGE VERSION
ip-192-168-31-151.ap-southeast-1.compute.internal Ready 13m v1.20.4-eks-6b7464
ip-192-168-54-97.ap-southeast-1.compute.internal Ready 13m v1.20.4-eks-6b7464
ip-192-168-74-140.ap-southeast-1.compute.internal Ready 13m v1.20.4-eks-6b7464

ปล. สำหรับท่านที่ใช้ k8s แล้วต้องการความสะดวก ในการ monitoring แนะนำ Lens ครับ สะดวกมากกว่าใช้ CLI (kubectl)
Lens: https://k8slens.dev/

เรียบร้อยละครับ เพียงเท่านี้ เราก็สามารถ เพิ่ม spec หรือ scale out EKS Cluster ของเรา ให้รองรับ load สูงๆ ได้แบบง่ายๆ และรวดเร็ว ทันใช้งาน ครับ 🙂

รายละเอียดเพิ่มเติม: https://docs.aws.amazon.com/eks/latest/userguide/migrate-stack.html

ทดสอบการใช้งาน OpenShift 4.2 (OCP4)

OCP4 (OpenShift 4.2)

สวัสดีครับ หลังจากที่ทดลองใช้งาน OpenShift 4.2 มาเดือนกว่าๆ ตั้งแต่เริ่มต้น Prepair Architecture
และร่วมกับ Vendor จากทาง Red Hat (MFEC) ทำการ Install ตลอดจนการแก้ไข จนเริ่มต้นใช้งานได้
เลยจะมาเขียนสรุปไว้เป็นความคิดเห็นสำหรับผู้ที่สนใจ จะใช้งานตัว OpenShift Container Platform (OCP4)

สำหรับตัว OpenShift 4.2 มีอะไรใหม่ๆ ออกมาเพิ่มเติมจาก 3.xx เยอะมาก อ่านรายละเอียดได้ที่
https://blog.openshift.com/introducing-red-hat-openshift-4-2-developers-get-an-expanded-and-improved-toolbox/

ในความคิดเห็นส่วนตัว สำหรับผม ที่ได้ลองเล่น ลองผิดลองถูกมาบ้าง ขอแบ่งเป็นข้อๆ ดังนี้

ข้อดี
– เป็น Enterprise Container Platform สำหรับ On-Premise ที่มี Support จาก Red Hat
– ใช้งานง่าย มี Template สำหรับหลายๆ Language ยอดนิยม, Database ที่เป็น Open Source และ CI/CD Tools
– มี Web Console ที่มี UI ใช้งานได้ง่าย แบ่งเป็น 2 Level คือ Developer/Admin
– มี CLI “oc” ที่ใกล้เคียงกับ “kubectl” ทำให้ใช้งานได้สะดวกสำหรับ คนที่ใช้ k8s มาก่อน
– สามารถ build microservices ได้จากหลากหลายวิธี จาก git และ template ที่มีมาให้
– สามารถมันจัดการ route ระดับ ingress ได้ดีมาก เราสามาถสำหนด endpoint ที่ต้องการได้ (HAProxy)
– มี Topology ที่ทำให้เห็น รายละเอียด และความสัมพันธ์ ระดับ service ได้ชัดเจน และจัดการตรงนี้ได้เลย
– มี Service Mesh ที่ทำให้รู้รายละเอียด ระดับ traffic ของแต่ละ service (Istio, Kiali and Jaeger)
– มี Images registry build-in มาด้วยในตัว
– มี Cloud-native CI/CD with Pipelines (Tekton) หรือจะใช้ Jenkins ด้วยก็ได้
– มี Dashboard และ Monitoring ที่ละเอียดจาก Grafana + Prometheus
– การใช้งานง่าย เหมาะสำหรับผู้เริ่มต้นใช้งาน Container
– Documents ตัว OpenShift จาก Red Hat เอง ค่อนข้างละเอียด และดีมาก

ข้อเสีย
– ราคาสำหรับตัว Enterprise ค่อนข้างสูง
– การ Install ระบบค่อนข้างวุ่นวาย ต้องใช้ การ config DNS และ LB ในการ Install
– เนื่องจากเป็น CoreOS ทำให้ มี tools ต่างๆ ในการวิเคราะห์ปัญหา ติดมาด้วยน้อยมาก
– สำหรับคนที่เคยใช้ Docker หรือ Kubernetes (k8s) มาก่อน ก็ใช่ว่าจะใช้งานง่าย +___+
– ด้วยความที่เน้น เรื่อง security ทำให้ หลายๆ Docker Images ไม่สามารถใช้งานบน OCP4 ได้

สำหรับใครที่อยากทดสอบการใช้งาน ก็เข้าไป Download ตัว Red Hat CodeReady Containers (CRC)
มาทดลองเล่นดูก่อนก็ได้ครับ (เครื่องต้องสเปคสูงหน่อย)
https://developers.redhat.com/products/codeready-containers

ผมเองก็ยังมือใหม่สำหรับ OpenShift 4.2 แต่แนวโน้ม บริษัทขนาดใหญ่ จะไปทางนี้กันหมด
ศึกษาไว้ ก็ไม่เสียหาย ใครที่ทดลองใช้งาน แล้วติดปัญหายังไง หรือมีอะไรจะแนะนำ
ก็เข้ามาพูดคุยกันได้นะครับ LINE ID: pornpasok 🙂