วิธีการติดตั้งและใช้งาน Flux (GitOps tool) บน Amazon EKS - Part 1
Tags: flux, gitops, eks, awsthai
Published: 2021-09-15 06:28:37

### Introduction
GitOps[1] เป็นการนำ tool, best practice และประโยชน์ต่างๆจาก Git และ Continuous Integration/Continuous Delivery (CI/CD) ที่มีการใช้งานกันเป็น standard ใน Software Development Life Cycle (SDLC) มาใช้ร่วมกับ Infrastructure as Code (IaC) ในทางฝั่งของ IT operation เพื่อจัดการกับ infrastructure ต่างๆ

Flux[2] เป็นหนึ่งใน GitOps tool ที่ได้รับได้ความนิยมในปัจจุบัน เพื่อใช้การใช้จัดการ resource ต่างๆบน Kubernetes cluster โดย version ที่ใช้ในปัจจุบันคือ Flux v2 ซึ่งตัว Flux operator ใน cluster จะทำการ pull ตัว declarative (IaC) จาก Git repository และทำการ reconcile Kubernetes resource ต่างๆให้ตรงตามนั้น

ใน blog post นี้เราจะมาดูการติดตั้งและใช้งาน Flux ในเบื้องต้นกัน

### Prerequisites
- ทำการติดตั้ง [`eksctl`](https://eksctl.io/introduction/#installation) และ [`flux`](https://fluxcd.io/docs/installation/)
- สร้าง [`personal access token`](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token) บน GitHub account

### How to setup Flux on Amazon EKS cluster
eksctl[3] เป็นหนึ่งใน standard tool ที่ใช้ในการสร้างและจัดการ EKS cluster และตั้งแต่ vesion `0.53.0` จะมี feature ในการติดตั้ง Flux รวมอยู่ด้วย

ขั้นตอนในการสร้าง EKS cluster ใหม่และติดตั้ง Flux โดยอัตโนมัติ

1. export ค่าต่างๆที่จะต้องใช้ในขั้นตอนต่อๆไป
    ```
    export GITHUB_USERNAME=<your GitHub username>
    export GITHUB_TOKEN=<your GitHub personal access token>
    ```

2. สร้าง config file ด้วย code ด้านล่างนี้และเปลี่ยน `<GitHub username>` เป็นชื่อ GitHub username ของเรา
    ```
    cat << EOF > eks-gitops-demo.yaml
    apiVersion: eksctl.io/v1alpha5
    kind: ClusterConfig

    metadata:
      name: eks-gitops-demo
      region: ap-southeast-1

    managedNodeGroups:
      - name: ng-1
        instanceType: m5.large
        desiredCapacity: 1

    gitops:
      flux:
        gitProvider: github
        flags:
          owner: "${GITHUB_USERNAME}"
          personal: "true"
          private: "true"
          repository: "eks-gitops-demo"
          branch: "master"
          namespace: "flux-system"
          path: "clusters/eks-gitops-demo"
    EOF
    ```

3. ทำการสร้าง EKS cluster โดยใช้คำสั่ง `eksctl create cluster --config-file eks-gitops-demo.yaml` และรอจน cluster สร้างเสร็จ

4. เราสามารถเช็ค resource ต่างๆที่เกี่ยวกับ Flux โดยใช้คำสั่ง `kubectl --namespace flux-system get all`
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s6jtbd9fsfcd1rwi4bwz.jpg)

5. และใน GitHub account ของเราจะมี repository ใหม่ที่ชื่อ `eks-gitops-demo` ถูกสร้างขึ้นมาและมี commit ในส่วนของ Kubernetes manifest file ของ Flux component ต่างๆ
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mhynb58ha1sold17px72.jpg)

ถึงตรงนี้แสดงว่าขั้นตอนการสร้าง EKS cluster ใหม่ที่มีการติดตั้ง Flux มาด้วยเป็นอันเสร็จสมบูรณ์แล้ว

Note. สำหรับกรณีที่เป็น EKS cluster เดิมหรือต้องการติดตั้ง Flux แยกทีหลัง
- ในกรณีที่ cluster ที่ถูกสร้างด้วย eksctl เราสามารถติดตั้ง Flux โดยการใช้คำสั่ง [`eksctl enable flux`](https://eksctl.io/usage/gitops-v2/) ได้
- ในกรณีที่ไม่ได้ใช้ eksctl เราสามารถติดตั้ง Flux โดยการใช้ flux CLI และคำสั่ง [`flux bootstrap`](https://fluxcd.io/docs/installation/)

### How to use Flux basic features
ต่อมาเราจะมาดูการใช้งาน Flux แบบเบื้องต้นกัน

ตัวอย่างแรกจะเป็นการใช้ Kubernetes manifest file ตามปกติ

1. เริ่มต้นจากการ clone GitHub repository ที่ Flux ได้สร้างขึ้นมา
    ```
    git clone git@github.com:${GITHUB_USERNAME}/eks-gitops-demo.git
    cd eks-gitops-demo
    ```

2. หลังจากนั้นเราจะสร้าง Kubernetes manifest file สำหรับ `nginx:1.14.2` deployment แล้วทำการ commit และ push ไปยัง GitHub
    ```
    mkdir -p clusters/eks-gitops-demo/default/nginx

    cat << EOF > clusters/eks-gitops-demo/default/nginx/deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
      labels:
        app: nginx
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:1.14.2
            ports:
            - containerPort: 80
    EOF

    git add clusters/eks-gitops-demo/default/nginx/deployment.yaml
    git commit -m "Add Nginx deployment"
    git push
    ```
3. ตามค่า default config Flux จะ pull ข้อมูลจาก GitHub ทุกๆ 10 นาทีและทำการ reconcile Kubernetes resource แต่เราสามารถใช้คำสั่ง `flux reconcile source git flux-system` เพื่อทำการ pull โดยทันทีได้
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wtob1udj0lzhomopaq3d.jpg)

4. หลังจากนั้นเราสามารถเช็คได้ว่า Flux ทำการ apply change ต่างๆและมีการสร้าง Kubernetes deployment ขึ้นมา โดยใช้คำสั่ง `kubectl get deployment nginx-deployment`
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xbusoxtmat7xu0bdq0ou.jpg)

5. หลังจากนั้นลองทำการเปลี่ยนใน deployment manifest file `nginx:1.15.0` และทำการ commit และ push ไปยัง GitHub อีกครั้งนึง
    ```
    sed -i '' 's/1.14.2/1.15.0/' clusters/eks-gitops-demo/default/nginx/deployment.yaml

    git add clusters/eks-gitops-demo/default/nginx/deployment.yaml
    git commit -m "Change Nginx image to 1.15.0"
    git push
    ```

6. หลังจาก Flux ทำการ reconcile เสร็จ จะเห็นได้ว่า deployment มีการเปลี่ยนไปใช้ `nginx:1.15.0`
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ra7rbztybg0rqm3mx8fc.jpg)

7.(Bonus) ถ้าลองลบ deployment manifest แล้วทำการ commit และ push ไปยัง GitHub หลังจาก Flux ทำการ reconcile เสร็จ จะเห็นได้ว่าตัว deployment ของ nginx จะถูกลบไปเช่นกัน

อีกตัวอย่างนึงจะเป็นการใช้งาน Flux ร่วมกับ Helm

1. เริ่มต้นจากการสร้าง HelmRepository CRD ที่ชี้ไปยัง Helm Chart repository ในตัวอย่างนี้เราจะใช้ [`prometheus-community`](https://prometheus-community.github.io/helm-charts)
    ```
    mkdir -p clusters/eks-gitops-demo/monitoring

    cat << EOF > clusters/eks-gitops-demo/monitoring/namespace.yaml
    apiVersion: v1
    kind: Namespace
    metadata:
      name: monitoring
    EOF
    ---
    cat << EOF > clusters/eks-gitops-demo/monitoring/prometheus-community.yaml
    apiVersion: source.toolkit.fluxcd.io/v1beta1
    kind: HelmRepository
    metadata:
      name: prometheus-community
      namespace: monitoring
    spec:
      url: https://prometheus-community.github.io/helm-charts
      interval: 10m
    EOF
    ```

2. หลังจากนั้นทำการสร้าง HelmRelease CRD สำหรับที่จะให้ Flux deploy โดยใช้ Chart ที่ชื่อ `kube-prometheus-stack` หลังจากนั้นทำการ commit และ push ไปยัง GitHub
    ```
    mkdir -p clusters/eks-gitops-demo/monitoring

    cat << EOF > clusters/eks-gitops-demo/monitoring/namespace.yaml
    apiVersion: v1
    kind: Namespace
    metadata:
      name: monitoring
    EOF

    cat << EOF > clusters/eks-gitops-demo/monitoring/kube-prometheus-stack.yaml
    apiVersion: helm.toolkit.fluxcd.io/v2beta1
    kind: HelmRelease
    metadata:
      name: kube-prometheus-stack
      namespace: monitoring
    spec:
      releaseName: kube-prometheus-stack
      interval: 10m
      chart:
        spec:
          chart: kube-prometheus-stack
          sourceRef:
            kind: HelmRepository
            name: prometheus-community
            namespace: monitoring
    EOF

    git add clusters/eks-gitops-demo/monitoring/*
    git commit -m "Add Prometheus with Helm"
    git push
    ```

3. หลักจากนั้นใช้คำสั่ง `flux reconcile source git flux-system` เพื่อ pull change จาก GitHub และเนื่องจากใน HelmRelease CRD เราตั้ง interval ในการ reconcile เป็นทุกๆ 10 นาที เราสามารถใช้คำสั่ง `flux --namespace monitoring reconcile helmrelease kube-prometheus-stack` เพื่อให้ reconcile ทันทีได้เช่นกัน
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bpaokz1a1zb0b4iv74uh.jpg)

4. หลักจาก reconcile เสร็จสิ้น เราสามารถเช็คได้ว่า resource ต่างๆสำหรับ Prometheus ได้มีการติดตั้งใน cluster อย่างถูกต้องโดย Helm Chart ผ่าน Flux
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hur9rqc565v8oxi7n616.jpg)

### Conclusion
GitOps เป็นการนำเทคนิคและการใช้งาน Git, CI/CD และ IaC มาประกอบกันเพื่อให้เราสามารถจัดการ infrastructure ได้อย่างมีประสิทธิภาพและลดความผิดพลาดที่อาจจะเกิดขึ้นจาก manual process

Flux เป็น tool ที่ช่วยให้เราสามารถ implement GitOps บน Kubernetes ได้อย่างสะดวกยิ่งขึ้น ซึ่งใน blog post นี้เราได้เห็นวิธีการติดตั้งบน Amazon EKS ผ่าน eksctl

หลังจากนั้นเราได้เห็นตัวอย่างวิธีการติดใช้งาน Flux ในเบื้องต้น และใน part ที่ 2 เราจะมาดูตัวอย่างและ feature อื่นๆของ Flux กัน

### References
[1] https://www.gitops.tech/#what-is-gitops
[2] https://fluxcd.io/
[3] https://eksctl.io/
[4] https://helm.sh/