[{"content":"Introduction In today\u0026rsquo;s cloud-native world, container orchestration has become a must for scaling applications reliably. Kubernetes (K8s), an open-source orchestration platform, is the de facto standard for managing containers in production. But managing the control plane, networking, and high availability? That’s not something you want to handle manually.\nThat’s where Amazon EKS (Elastic Kubernetes Service) comes in. EKS is a managed Kubernetes service by AWS. It takes care of provisioning the control plane, automating upgrades, and integrating deeply with other AWS services like IAM, VPC, CloudWatch, and Load Balancers.\nTo simplify you and your team\u0026rsquo;s work, we can use GitHub Actions to automate build, test, and deployment for your applications that you want to run in Kubernetes.\nPrerequisites IAM Role – to manage AWS resource used by AWS CLI. ECR Repository – to save your container image. AWS CLI – to access AWS services from the command line. kubectl – to interact with the Kubernetes cluster. eksctl – to simplify EKS cluster creation and management. helm – to install Kubernetes applications. GitHub Account – to use GitHub Actions. Workflow Steps Configure AWS CLI We start by configuring AWS CLI so that your local machine can communicate with AWS using your access credentials.\naws configure You\u0026rsquo;ll be prompted to input your AWS credentials and default region:\nAWS Access Key ID [None]: YOUR_ACCESS_KEY AWS Secret Access Key [None]: YOUR_SECRET_KEY Default region name [None]: us-east-1 Default output format [None]: json Creating AWS EKS Cluster via eksctl This command uses eksctl to provision an entire Kubernetes cluster on AWS, including the control plane and worker nodes. eksctl create cluster --name my-cluster --region us-east-1 Configure Load Balancer IngressClass Associate the IAM OIDC provider so service accounts can assume roles.\neksctl utils associate-iam-oidc-provider --region us-east-1 --cluster my-cluster --approve Download the IAM policy for the AWS Load Balancer Controller.\ncurl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/refs/heads/main/docs/install/iam_policy.json Create the IAM policy in AWS using the downloaded JSON file.\naws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam-policy.json Get your current AWS account ID.\naws sts get-caller-identity --query \u0026#34;Account\u0026#34; --output text Create a Kubernetes service account and attach the IAM policy to it.\neksctl create iamserviceaccount --cluster=my-cluster --namespace=kube-system --name=aws-load-balancer-controller --attach-policy-arn=arn:aws:iam::\u0026lt;AWSAccountNumber\u0026gt;:policy/AWSLoadBalancerControllerIAMPolicy --override-existing-serviceaccounts --region us-east-1 --approve Add the EKS Helm chart repo.\nhelm repo add eks https://aws.github.io/eks-charts Update your Helm repositories.\nhelm repo update eks Get your VPC ID associated with the EKS cluster.\naws ec2 describe-vpcs --filters \u0026#34;Name=tag:eksctl.cluster.k8s.io/v1alpha1/cluster-name,Values=my-cluster\u0026#34; --query \u0026#34;Vpcs[0].VpcId\u0026#34; --output text Install the AWS Load Balancer Controller via Helm.\nhelm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=my-cluster --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller --set region=us-east-1 --set vpcId=\u0026lt;yourVPCID\u0026gt; Deploying WebApp using GitHub Actions First thing first, you need an application that you wanna deploy to EKS. Here I\u0026rsquo;m deploying a simple tetris game Canvas Tetris.\nTo create an automated deployment, you need a workflow file placed in the .github/workflows directory in your repo with a .yaml extension. The workflow below builds and deploys the app to EKS on every push to the master branch.\nname: Deploy to Amazon EKS on: push: branches: - master env: AWS_REGION: ${{ vars.AWS_REGION }} ECR_REPOSITORY: ${{ vars.ECR_REPOSITORY }} EKS_CLUSTER_NAME: ${{ vars.EKS_CLUSTER_NAME }} permissions: id-token: write contents: read jobs: build: name: Build Image runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Set short git commit SHA id: commit uses: prompt/actions-commit-hash@v2 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }} aws-region: ${{ env.AWS_REGION }} - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1 - name: Build, tag, and push image to Amazon ECR id: build-image env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} IMAGE_TAG: ${{ steps.commit.outputs.short || \u0026#39;latest\u0026#39; }} run: | docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - name: End Build run: echo \u0026#34;Build Success\u0026#34; deploy: name: Deploy Application needs: build runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Set short git commit SHA id: commit uses: prompt/actions-commit-hash@v2 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }} aws-region: ${{ env.AWS_REGION }} - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1 - name: Update kube config run: aws eks update-kubeconfig --name $EKS_CLUSTER_NAME --region $AWS_REGION - name: Deploy to EKS env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} IMAGE_TAG: ${{ steps.commit.outputs.short || \u0026#39;latest\u0026#39; }} run: | sed -i \u0026#34;s|DOCKER_IMAGE|$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG|g\u0026#34; manifests/deployment.yaml \u0026amp;\u0026amp; \\ kubectl apply -f manifests/deployment.yaml kubectl apply -f manifests/service.yaml kubectl apply -f manifests/ingress.yaml As seen above, we also use environment variables (env and secrets) to keep the workflow dynamic and secure. For more info on setting those, check GitHub’s official docs.\n","permalink":"https://rifkyards.github.io/blogs/aws/integrate-eks-and-github-actions/","summary":"\u003ch1 id=\"introduction\"\u003eIntroduction\u003c/h1\u003e\n\u003cp\u003eIn today\u0026rsquo;s cloud-native world, container orchestration has become a must for scaling applications reliably. Kubernetes (K8s), an open-source orchestration platform, is the de facto standard for managing containers in production. But managing the control plane, networking, and high availability? That’s not something you want to handle manually.\u003c/p\u003e\n\u003cp\u003eThat’s where Amazon EKS (Elastic Kubernetes Service) comes in. EKS is a managed Kubernetes service by AWS. It takes care of provisioning the control plane, automating upgrades, and integrating deeply with other AWS services like IAM, VPC, CloudWatch, and Load Balancers.\u003c/p\u003e","title":"Integrate AWS EKS and GitHub Actions"},{"content":"Blog ini merupakan kelanjutan dari bagian sebelumnya. Jika belum membacanya, bisa cek disini.\nLangkah Implementasi Instalasi dan Konfigurasi Tools Prometheus. Note : Lakukan langkah dibawah ini di monitoring node.\nDownload dan ekstrak file Prometheus. ~$ sudo su - ~# cd /opt /opt# wget https://github.com/prometheus/prometheus/releases/download/v2.48.1/prometheus-2.48.1.linux-amd64.tar.gz /opt# tar xvfz prometheus-2.48.1.linux-amd64.tar.gz Menambahkan file konfigurasi untuk Prometheus. /opt# cd prometheus-2.48.1. linux-amd64 /opt/prometheus-2.48.1. linux-amd64# vim config.yml --- global: scrape_interval: 10s evaluation_interval: 15s scrape_configs: - job_name: \u0026#39;node\u0026#39; scrape_interval: 5s static_configs: - targets: [\u0026#39;192.168.4.10:9100\u0026#39;,\u0026#39;192.168.4.20:9100\u0026#39;,\u0026#39;192.168.4.30:9100\u0026#39;] - job_name: \u0026#39;nginx\u0026#39; static_configs: - targets: [\u0026#39;192.168.4.20:9113\u0026#39;] - job_name: \u0026#39;cadvisor\u0026#39; static_configs: - targets: [\u0026#39;192.168.4.30:8080\u0026#39;] - job_name: \u0026#39;docker\u0026#39; static_configs: - targets: [\u0026#39;192.168.4.30:9323\u0026#39;] alerting: alertmanagers: - static_configs: - targets: - 192.168.4.10:9093 rule_files: - \u0026#34;rules/container.yml\u0026#34; - \u0026#34;rules/node.yml\u0026#34; - \u0026#34;rules/web-server.yml\u0026#34; Membuat SSL Key dan Certificate Signing Request. /opt/prometheus-2.48.1.linux-amd64# sudo openssl genrsa -out /opt/prometheus-2.48.1.linux-amd64/prometheus.key 2048 /opt/prometheus-2.48.1.linux-amd64# sudo openssl req -new -key /opt/prometheus-2.48.1.linux-amd64/prometheus.key -out /opt/prometheus-2.48.1.linux-amd64/prometheus.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter \u0026#39;.\u0026#39;, the field will be left blank. Country Name (2 letter code) [AU]:ID State or Province Name (full name) [Some-State]: South Kalimantan Locality Name (eg, city) []:Banjarbaru Organization Name (eg, company) [Internet Widgits Pty Ltd]: Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []: Email Address []: Please enter the following \u0026#39;extra\u0026#39; attributes to be sent with your certificate request A challenge password []: An optional company name []: Membuat SSL Self-Signed Certificate. /opt/prometheus-2.48.1.linux-amd64# openssl x509 -req -days 365 -signkey prometheus.key -in prometheus.csr -out prometheus.crt -extfile \u0026lt;(echo \u0026#34;subjectAltName=IP:192.168.4.10\u0026#34; ) Certificate request self-signature ok subject=C = ID, ST = South Kalimantan, L = Banjarbaru, O = Internet Widgits Pty Ltd Instalasi paket yang dibutuhkan untuk basic authentication. ~# sudo apt-get update \u0026amp;\u0026amp; sudo apt install apache2-utils -y Membuat password untuk basic authentication. ~# htpasswd -nBC 12 \u0026#34;\u0026#34; | tr -d \u0026#39;:\\n\u0026#39; New password: \u0026lt;inputYourPassword\u0026gt; Re-type new password: \u0026lt;inputYourPassword\u0026gt; $2y$12$\u0026lt;saltAndHash\u0026gt; Menambahkan konfigurasi untuk web agar SSL dan basic authentication diterapkan. /opt/prometheus-2.48.1. linux-amd64# vim web.yml basic_auth_users: rifkyards: $2y$12$\u0026lt;saltAndHash\u0026gt; tls_server_config: cert_file: /opt/prometheus-2.48.1.linux-amd64/prometheus.crt key_file: /opt/prometheus-2.48.1.linux-amd64/prometheus.key Menambahkan rules untuk mengirimkan alert node yang mati ke Alert Manager. /opt/prometheus-2.48.1.linux-amd64# vim rules/node.yml # Add this lines groups: - name: NodeStatus rules: - alert: \u0026#34;NodeMonitoringDown\u0026#34; expr: up{instance=\u0026#34;192.168.4.10:9100\u0026#34;} == 0 for: 5m labels: severity: critical instance: \u0026#34;{{ $labels.instance }}\u0026#34; alertname: \u0026#34;NodeMonitoringDown\u0026#34; annotations: title: \u0026#34;{{ $labels.instance }} is down\u0026#34; description: \u0026#34;The server with IP {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34; - alert: \u0026#34;NodeClient1Down\u0026#34; expr: up{instance=\u0026#34;192.168.4.10:9100\u0026#34;} == 0 for: 5m labels: severity: critical instance: \u0026#34;{{ $labels.instance }}\u0026#34; alertname: NodeClient1Down annotations: title: \u0026#34;{{ $labels.name }} is down\u0026#34; description: \u0026#34;The server with IP {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34; - alert: \u0026#34;NodeClient2Down\u0026#34; expr: up{instance=\u0026#34;192.168.4.30:9100\u0026#34;} == 0 for: 5m labels: severity: critical instance: \u0026#34;{{ $labels.instance }}\u0026#34; alertname: NodeClient2Down annotations: title: \u0026#34;{{ $labels.instance }} is down\u0026#34; description: \u0026#34;The server with IP {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34; Menambahkan rules untuk mengirimkan alert Nginx Server yang mati ke Alert Manager. /opt/prometheus-2.48.1.linux-amd64# vim rules/web-server.yml # Add this lines groups: - name: WebNginxStatus rules: - alert: NginxDown expr: nginx_up{instance=\u0026#34;192.168.4.20:9113\u0026#34;, job=\u0026#34;nginx\u0026#34;} == 0 for: 5m labels: severity: critical instance: \u0026#34;{{ $labels.instance }}\u0026#34; alertname: NginxDown annotations: title: \u0026#34;{{ $labels.name }} is down\u0026#34; description: \u0026#34;The {{ $labels.job }} server on {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34; Menambahkan rules untuk mengirimkan alert container yang mati ke Alert Manager. /opt/prometheus-2.48.1.linux-amd64# vim rules/container.yml # Add this lines groups: - name: containerMonitoring rules: - alert: \u0026#34;Container2048Down\u0026#34; expr: absent(container_start_time_seconds{name=\u0026#34;2048-apps\u0026#34;,instance=\u0026#34;192.168.4.30:8080\u0026#34;}) for: 5m labels: severity: critical instance: \u0026#34;{{ $labels.instance }}\u0026#34; alertname: Container2048Down annotations: title: \u0026#34;{{ $labels.name }} is down\u0026#34; description: \u0026#34;The {{ $labels.name }} container on {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34; - alert: \u0026#34;ContainerTicTacToeDown\u0026#34; expr: absent(container_start_time_seconds{name=\u0026#34;tic-tac-toe-apps\u0026#34;,instance=\u0026#34;192.168.4.30:8080\u0026#34;}) for: 5m labels: severity: critical instance: \u0026#34;{{ $labels.instance }}\u0026#34; alertname: ContainerTicTacToeDown annotations: title: \u0026#34;{{ $labels.name }} is down\u0026#34; description: \u0026#34;The {{ $labels.name }} container on {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34; - alert: \u0026#34;GeneralContainerDown\u0026#34; expr: time() - container_last_seen{instance=\u0026#34;192.168.4.30:8080\u0026#34;, image!=\u0026#34;\u0026#34;, name!~\u0026#34;2048-apps|tic-tac-toe-apps|cadvisor\u0026#34;} \u0026gt; 220 for: 20s labels: severity: critical instance: \u0026#34;{{ $labels.instance }}\u0026#34; alertname: GeneralContainerDown resolved: \u0026#39;false\u0026#39; annotations: title: \u0026#34;{{ $labels.name }} is down\u0026#34; description: \u0026#34;A container {{ $labels.name }} on {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34; Menambahkan konfigurasi untuk Prometheus berjalan di SystemD. ~# vim /etc/systemd/system/prometheus_server.service # Add this lines [Unit] Description=Prometheus Server [Service] User=root ExecStart=/opt/prometheus-2.48.1.linux-amd64/prometheus --config.file=/opt/prometheus-2.48.1.linux-amd64/config.yml --web.config.file=/opt/prometheus-2.48.1.linux-amd64/web.yml --web.external-url=https://192.168.4.10:9090/ [Install] WantedBy=default.target Menjalankan perintah agar SystemD Prometheus berjalan. ~# systemctl daemon-reload ~# systemctl start prometheus_server ~# systemctl enable prometheus_server Instalasi dan Konfigurasi Tools Alert Manager. Note : Lakukan langkah dibawah ini di monitoring node.\nDownload dan ekstrak file Alert Manager. ~$ sudo su - ~# cd /opt /opt# wget https://github.com/prometheus/alertmanager/releases/download/v0.26.0/alertmanager-0.26.0.linux-amd64.tar.gz /opt# tar xvfz alertmanager-0.26.0.linux-amd64.tar.gz Sebelum itu, karena Alert Manager perlu adanva akses ke email yang akan disetting dan juga bot pada platform Telegram.\nUntuk akses ke email, bisa menggunakan password dari email atau bisa pakai \u0026ldquo;App Password\u0026rdquo;. Berikut panduan yang bisa penulis kasih untuk pembuatan \u0026ldquo;App Password\u0026rdquo; : https://support.google.com/mail/answer/185833?hl=en Untuk platform Telegram, bisa membuat bot dan Alert Manager akan memakai kredensial dari bot yang dibuat. Berikut panduan yang bisa penulis kasih untuk pembuatan bot di Telegram : https://linuxtech.in/how-to-send-alerts-and-notifications-with-telegram/ Menambahkan konfigurasi untuk Alert Manager.\n/opt# cd alertmanager-0.26.0.linux-amd64 /opt/alertmanager-0.26.0.linux-amd64# vim config.yml # Add this lines global: resolve_timeout: 5m route: group_by: [\u0026#39;Alertname\u0026#39;] receiver: combined-receiver routes: - match: resolved: \u0026#34;false\u0026#34; receiver: combined-receiver-no-resolved - receiver: combined-receiver receivers: - name: combined-receiver email_configs: - to: \u0026#34;\u0026lt;yourEmail\u0026gt;@gmail.com\u0026#34; from: \u0026#34;\u0026lt;yourEmail\u0026gt;@gmail.com\u0026#34; smarthost: smtp.gmail.com:587 auth_username: \u0026#34;\u0026lt;yourEmail\u0026gt;@gmail.com\u0026#34; auth_identity: \u0026#34;\u0026lt;yourEmail\u0026gt;@gmail.com\u0026#34; auth_password: \u0026#34;xxxx xxxx xxxx\u0026#34; send_resolved: True headers: subject: \u0026#39;{{ template \u0026#34;__subject\u0026#34; . }}\u0026#39; html: \u0026#39;{{ template \u0026#34;email.custom.html\u0026#34; . }}\u0026#39; telegram_configs: - api_url: https://api.telegram.org bot_token: \u0026#34;\u0026lt;yourBotToken\u0026gt;\u0026#34; chat_id: \u0026lt;yourChatID\u0026gt; send_resolved: True message: \u0026#39;{{ template \u0026#34;telegram.message\u0026#34; . }}\u0026#39; - name: combined-receiver-no-resolved email_configs: - to: \u0026#34;\u0026lt;yourEmail\u0026gt;@gmail.com\u0026#34; from: \u0026#34;\u0026lt;yourEmail\u0026gt;@gmail.com\u0026#34; smarthost: smtp.gmail.com:587 auth_username: \u0026#34;\u0026lt;yourEmail\u0026gt;@gmail.com\u0026#34; auth_identity: \u0026#34;\u0026lt;yourEmail\u0026gt;@gmail.com\u0026#34; auth_password: \u0026#34;xxxx xxxx xxxx\u0026#34; send_resolved: False headers: subject: \u0026#39;{{ template \u0026#34;__subject\u0026#34; . }}\u0026#39; html: \u0026#39;{{ template \u0026#34;email.custom.html\u0026#34; . }}\u0026#39; telegram_configs: - api_url: https://api.telegram.org bot_token: \u0026#34;\u0026lt;yourBotToken\u0026gt;\u0026#34; chat_id: \u0026lt;yourChatID\u0026gt; send_resolved: False message: \u0026#39;{{ template \u0026#34;telegram.message\u0026#34; . }}\u0026#39; templates: - \u0026#39;templates/telegram.tmpl\u0026#39; - \u0026#39;templates/email.tmpl\u0026#39; Menambahkan file template untuk telegram. /opt/alertmanager-0.26.0.linux-amd64# vim template/telegram.tmpl # Add this lines {{ define \u0026#34;telegram.message\u0026#34; }} {{ if eq .Status \u0026#34;firing\u0026#34; }} {{ if eq .CommonLabels.severity \u0026#34;critical\u0026#34; }}🔴 Alert: {{ .CommonLabels.alertname }} {{ else if eq .CommonLabels.severity \u0026#34;warning\u0026#34; }}🟠 Alert: {{ .CommonLabels.alertname }} {{ else }}⚪️ Alert: {{ .CommonLabels.alertname }} {{ end }} Status: 🔥 FIRING Severity: {{ if eq .CommonLabels.severity \u0026#34;critical\u0026#34; }}🔴 {{ .CommonLabels.severity | title }}{{ else if eq .CommonLabels.severity \u0026#34;warning\u0026#34; }}🟠 {{ .CommonLabels.severity | title }}{{ else }}⚪️ {{ .CommonLabels.severity | title }}{{ end }} {{ else if eq .Status \u0026#34;resolved\u0026#34; }} {{ if eq .CommonLabels.severity \u0026#34;critical\u0026#34; }}🟢 🚌 TRANSPORT Alert: {{ .CommonLabels.alertname }} {{ else if eq .CommonLabels.severity \u0026#34;warning\u0026#34; }}🟢 🚌 TRANSPORT Alert: {{ .CommonLabels.alertname }} {{ else }}⚪️ Alert: {{ .CommonLabels.alertname }} {{ end }} Status: ✅ RESOLVED Severity: {{ if eq .CommonLabels.severity \u0026#34;critical\u0026#34; }}🟢 {{ .CommonLabels.severity | title }}{{ else if eq .CommonLabels.severity \u0026#34;warning\u0026#34; }}🟢 {{ .CommonLabels.severity | title }}{{ else }}⚪️ {{ .CommonLabels.severity | title }}{{ end }} {{ end }} {{ range .Alerts }} Instance: {{ .Labels.instance }} - Title: {{ .Annotations.title }} - Description: {{ .Annotations.description }} Source: {{ .GeneratorURL | reReplaceAll \u0026#34;\u0026amp;g0.tab=1$\u0026#34; \u0026#34;\u0026amp;g0.tab=0\u0026#34; }} {{ end }} {{ end }} Menambahkan file template untuk email. /opt/alertmanager-0.26.0.linux-amd64# vim template/email.tmpl {{ define \u0026#34;__subject\u0026#34; }} {{ if and .Alerts.Firing .Alerts.Resolved }} [INFO - Firing: {{ len .Alerts.Firing }} - Resolved: {{ len .Alerts.Resolved }}] {{ else if eq .Status \u0026#34;firing\u0026#34; }} [FIRING: {{ if .Alerts.Firing }}{{ len .Alerts.Firing }}{{ else }}0{{ end }} - {{ if eq (len .Alerts.Firing) 1 }}{{ .CommonLabels.alertname }} - {{ .CommonLabels.instance }} - {{ .CommonLabels.severity | title }}{{ else }}Many Alerts{{ end }}] {{ else if eq .Status \u0026#34;resolved\u0026#34; }} [RESOLVED: {{ if .Alerts.Resolved }}{{ len .Alerts.Resolved }}{{ else }}0{{ end }} - {{ if eq (len .Alerts.Resolved) 1 }}{{ .CommonLabels.alertname }}{{ else }}Many Alerts{{ end }}] {{ else }} [UNKNOWN] {{ end }} {{ end }} {{ define \u0026#34;email.custom.html\u0026#34; }} \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html xmlns=\u0026#34;http://www.w3.org/1999/xhtml\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width\u0026#34; /\u0026gt; \u0026lt;meta http-equiv=\u0026#34;Content-Type\u0026#34; content=\u0026#34;text/html; charset=UTF-8\u0026#34; /\u0026gt; \u0026lt;title\u0026gt;{{ template \u0026#34;__subject\u0026#34; . }}\u0026lt;/title\u0026gt; \u0026lt;style\u0026gt; body { font-family: Arial, sans-serif; color: #333; } h1 { color: #d9534f; /* Red color for headings */ } .alert-table { width: 100%; border-collapse: collapse; margin-top: 20px; } .alert-table th, .alert-table td { padding: 10px; border: 1px solid #ddd; } .alert-table th { background-color: #f9f9f9; } .alert-table tr:nth-child(even) { background-color: #f2f2f2; } .alert-table td a { color: #007bff; text-decoration: none; } .alert-table td a:hover { text-decoration: underline; } \u0026lt;/style\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Dear Team,\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;Total Resolved Alerts: {{ .Alerts.Resolved | len }}\u0026lt;/p\u0026gt; \u0026lt;h2\u0026gt;Firing Alerts\u0026lt;/h2\u0026gt; {{ if gt (len .Alerts.Firing) 0 }} \u0026lt;table class=\u0026#34;alert-table\u0026#34;\u0026gt; \u0026lt;tr\u0026gt; \u0026lt;th\u0026gt;Instance\u0026lt;/th\u0026gt; \u0026lt;th\u0026gt;Severity\u0026lt;/th\u0026gt; \u0026lt;th\u0026gt;Description\u0026lt;/th\u0026gt; \u0026lt;th\u0026gt;Source\u0026lt;/th\u0026gt; \u0026lt;/tr\u0026gt; {{ range .Alerts.Firing }} \u0026lt;tr\u0026gt; \u0026lt;td\u0026gt;{{ .Labels.instance }}\u0026lt;/td\u0026gt; \u0026lt;td\u0026gt;{{ .Labels.severity }}\u0026lt;/td\u0026gt; \u0026lt;td\u0026gt;{{ if .Annotations.description }}{{ .Annotations.description }}{{ else }}N/A{{ end }}\u0026lt;/td\u0026gt; \u0026lt;td\u0026gt;\u0026lt;a href=\u0026#34;{{ .GeneratorURL }}\u0026#34;\u0026gt;Source\u0026lt;/a\u0026gt;\u0026lt;/td\u0026gt; \u0026lt;/tr\u0026gt; {{ end }} \u0026lt;/table\u0026gt; {{ else }} \u0026lt;p\u0026gt;No active firing alerts.\u0026lt;/p\u0026gt; {{ end }} \u0026lt;h2\u0026gt;Resolved Alerts\u0026lt;/h2\u0026gt; {{ if gt (len .Alerts.Resolved) 0 }} \u0026lt;table class=\u0026#34;alert-table\u0026#34;\u0026gt; \u0026lt;tr\u0026gt; \u0026lt;th\u0026gt;Instance\u0026lt;/th\u0026gt; \u0026lt;th\u0026gt;Severity\u0026lt;/th\u0026gt; \u0026lt;th\u0026gt;Description\u0026lt;/th\u0026gt; \u0026lt;th\u0026gt;Source\u0026lt;/th\u0026gt; \u0026lt;/tr\u0026gt; {{ range .Alerts.Resolved }} \u0026lt;tr\u0026gt; \u0026lt;td\u0026gt;{{ .Labels.instance }}\u0026lt;/td\u0026gt; \u0026lt;td\u0026gt;{{ .Labels.severity }}\u0026lt;/td\u0026gt; \u0026lt;td\u0026gt;{{ if .Annotations.description }}{{ .Annotations.description }}{{ else }}N/A{{ end }}\u0026lt;/td\u0026gt; \u0026lt;td\u0026gt;\u0026lt;a href=\u0026#34;{{ .GeneratorURL }}\u0026#34;\u0026gt;Source\u0026lt;/a\u0026gt;\u0026lt;/td\u0026gt; \u0026lt;/tr\u0026gt; {{ end }} \u0026lt;/table\u0026gt; {{ else }} \u0026lt;p\u0026gt;No resolved alerts.\u0026lt;/p\u0026gt; {{ end }} \u0026lt;p\u0026gt;Best regards,\u0026lt;br\u0026gt;Monitoring System\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; {{ end }} Menambahkan konfigurasi untuk Alert Manager berjalan di SystemD. /opt/alertmanager-0.26.0.linux-amd64# vim /etc/systemd/system/alert_manager.service [Unit] Description=Alert Manager [Service] User=root ExecStart=/opt/alertmanager-0.26.0.linux-amd64/alertmanager --config.file=/opt/alertmanager-0.26.0.linux-amd64/config.yml --web.external-url=http://192.168.4.10:9093/ --log.level=debug [Install] WantedBy=default.target Menjalankan perintah agar SystemD Alert Manager berjalan. ~# systemctl daemon-reload ~# systemctl start alert_manager ~# systemctl enable alert_manager Instalasi dan Konfigurasi Tools Grafana. Note : Lakukan langkah dibawah ini di monitoring node.\nDownload dan ekstrak file Grafana. ~$ sudo su - ~# cd /opt ~# wget https://dl.grafana.com/oss/release/grafana-10.2.2.linux-amd64.tar.gz ~# tar -zxvf grafana-10.2.2.linux-amd64.tar.gz Membuat SSL Key. /opt# cd grafana-v10.2.2 /opt/grafana-v10.2.2# sudo openssl genrsa -out /opt/grafana-v10.2.2/grafana.key 2048 Membuat SSL Certificate Signing Request. /opt/grafana-v10.2.2# sudo openssl req -new -key /opt/grafana-v10.2.2/grafana.key -out /opt/grafana-v10.2.2/grafana.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter \u0026#39;.\u0026#39;, the field will be left blank. Country Name (2 letter code) [AU]:ID State or Province Name (full name) [Some-State]: South Kalimantan Locality Name (eg, city) []:Banjarbaru Organization Name (eg, company) [Internet Widgits Pty Ltd]: Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []: Email Address []: Please enter the following \u0026#39;extra\u0026#39; attributes to be sent with your certificate request A challenge password []: An optional company name []: Membuat SSL Self-Signed Certificate. /opt/grafana-v10.2.2# sudo openssl x509 -req -days 365 -in /opt/grafana-v10.2.2/grafana.csr -signkey /opt/grafana-v10.2.2/grafana.key -out /opt/grafana-v10.2.2/grafana.crt Certificate request self-signature ok subject=C = ID, ST = South Kalimantan, L = Banjarbaru, O = Internet Widgits Pty Ltd Konfigurasi untuk menerapkan SSL. /opt/grafana-v10.2.2# vim config.ini # Add this lines [server] http_addr = 192.168.4.10 http_port = 3000 root_url = https://192.168.4.10:3000 cert_key = /opt/grafana-v10.2.2/grafana.key cert_file = /opt/grafana-v10.2.2/grafana.crt enforce_domain = False protocol = https Konfigurasi untuk Grafana berjalan di SystemD. /opt/grafana-v10.2.2# vim /etc/systemd/system/grafana.service # Add this lines [Unit] Description=Grafana [Service] User=root ExecStart=/opt/grafana-v10.2.2/bin/grafana-server --config /opt/grafana-v10.2.2/config.ini -homepath /opt/grafana-v10.2.2/ web [Install] WantedBy=default.target Menjalankan perintah agar SystemD Grafana berjalan. ~# systemctl daemon-reload ~# systemctl start grafana ~# systemctl enable grafana Setting Grafana Dashboard. Akses dashboard grafana di https://192.168.4.10:3000 dengan default user dan password. Karena SSL Self-Signed, bisa di “Accept the Risk and Continue”. Integrasi Prometheus dengan Grafana, dengan mengakses garis tiga dipojok kiri \u0026gt; “Connections” \u0026gt; “Data Sources”. Setelah masuk di “Data Sources”, bisa tambahkan kita tambahkan “Data Sources” untuk integrasi dengan Prometheus. Bisa di klik “Add new data source”. Menambahkan endpoint dan basic authentication untuk Prometheus. Sebelum itu, kita dapatkan isi konten dari Self-Signed certificate Prometheus terlebih dahulu.\n/opt/prometheus-2.48.1.linux-amd64# cat prometheus.crt -----BEGIN CERTIFICATE----- XXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXxXXXXXXXXXXXXXXXXXXXXXX -----END CERTIFICATE------ Isi identitas user dan password yang kita buat untuk Prometheus, dan juga isi Self-Signed Certificate dengan isi konten dari file “prometheus.crt”. Scroll hingga paling bawah, bisa di klik “Save \u0026amp; test”. Jika berhasil akan muncul “Successfully queried the Prometheus API”. Setelah integrasi Grafana dan Prometheus, barulah kita buat dashboard untuk monitoring metrics. Klik garis tiga dipojok kiri \u0026gt; “Dashboards”. Setelah masuk pada halaman Dashboards, klik “New” \u0026gt; “New Dashboards”. Saat masuk pada halaman pembuatan dashboard, klik “Add visualization”. Lalu pilih Prometheus yang dibuat sebelumnya sebagai data sources. Saatnya membuat dashboard panel yang pertama, untuk menjawab pertanyaan “Apakah Nginx web server kita nyala atau mati?”.\nMenambahkan query :\nnginx_up{instance=\u0026quot;192.168.4.20:9113\u0026quot;, job=\u0026quot;nginx\u0026quot;} Lalu mengubah visualiasasi menjadi “Stat”, mengubah nama panel, dan mengubah “Color Mode”. Menambahkan “Value mappings” agar mengubah data menjadi UP or DOWN, dan hapus untuk “Thresholds” dengan nilai 80. Dan klik “Apply” untuk menerapkan konfigurasi panel. Untuk menambahkan panel baru, bisa klik “Add” \u0026gt; “Visualization”. Selanjutnya membuat dashboard panel untuk menjawab pertanyaan “Apakah aplikasi container kita nyala atau mati?”.\nMenambahkan query :\n(container_start_time_seconds{name=\u0026quot;2048-apps\u0026quot;} \u0026gt; 0) ^ 0 or absent(container_start_time_seconds{name=\u0026quot;2048-apps\u0026quot;}) * 0 Lalu mengubah visualisasi menjadi “Stat”, mengubah nama panel, dan mengubah “Color Mode”. Klik “Add Query” untuk menambahkan query :\n(container_start_time_seconds{name=\u0026quot;tic-tac-toe-apps\u0026quot;} \u0026gt; 0) ^ 0 or absent(container_start_time_seconds{name=\u0026quot;tic-tac-toe-apps\u0026quot;}) * 0 Lalu menambahkan “Value mappings” agar mengubah data menjadi UP or DOWN, dan hapus untuk “Thresholds” dengan nilai 80. Dan klik “Apply” untuk menerapkan setting. Selanjutnya membuat dashboard panel untuk menjawab pertanyaan “Berapa lama node sudah berjalan?”.\nMenambahkan query :\n(time() - process_start_time_seconds{instance=\u0026quot;192.168.4.10:9100\u0026quot;}) Lalu mengubah visualisasi menjadi “Stat”, mengubah nama panel, dan mengubah “Color Mode”. Klik “Add Query” untuk menambahkan query :\n(time() - process_start_time_seconds{instance=\u0026quot;192.168.4.20:9100\u0026quot;}) Lalu menganti “Unit” menjadi “seconds(s)”. Klik “Add Query” untuk menambahkan query :\n(time() - process_start_time_seconds{instance=\u0026quot;192.168.4.30:9100\u0026quot;}) Lalu hapus untuk “Thresholds” dengan nilai 80. Dan klik “Apply” untuk menerapkan setting. Selanjutnya membuat dashboard panel untuk menjawab pertanyaan “Berapa rata-rata request pada Nginx dalam kurun waktu 10 menit?”.\nMenambahkan query :\nrate(nginx_http_requests_total[10m]) Lalu mengubah nama panel. Lalu bisa juga untuk hapus “Thresholds” dengan nilai 80, dan klik “Apply” untuk menerapkan setting. Selanjutnya membuat dashboard panel untuk menjawab pertanyaan “Berapa banyak container yang dipause, distop, maupun berjalan?”.\nMenambahkan query :\nengine_daemon_container_states_containers{state=\u0026quot;running\u0026quot;} Lalu mengubah visualisasi menjadi “Bar Gauge”, mengubah nama panel, dan mengubah “Orientation”, “Display mode”, dan “Name placement”. Klik “Add Query” untuk menambahkan query :\nengine_daemon_container_states_containers{state=\u0026quot;stopped\u0026quot;} Lalu menganti “Text size” pada “Title” menjadi 20 dan hapus “Thresholds”. Klik “Add Query” untuk menambahkan query :\nengine_daemon_container_states_containers{state=\u0026quot;paused\u0026quot;} Lalu mengganti “Color Scheme”. Lalu klik “Apply” untuk menerapkan setting. Selanjutnya membuat dashboard panel untuk menjawab pertanyaan “Berapa banyak container yang mati dan berjalan?”.\nMenambahkan query :\nengine_daemon_container_states_containers{state=\u0026quot;running\u0026quot;} Lalu mengubah visualisasi menjadi “Bar Gauge”, mengubah nama panel, dan mengubah “Orientation”, “Display mode”, dan “Name placement”. Klik “Add Query” untuk menambahkan query :\nsum(engine_daemon_container_states_containers{state=\u0026quot;paused\u0026quot;}) + sum(engine_daemon_container_states_containers{state=\u0026quot;stopped\u0026quot;}) Lalu mengganti “Color Scheme” dan hapus “Thresholds”. Lalu klik “Apply” untuk menerapkan setting. Selanjutnya membuat dashboard panel untuk menjawab pertanyaan “Berapa persen penggunaan memory pada tiap node?”.\nMenambahkan query :\n(node_memory_MemTotal_bytes{instance=\u0026quot;192.168.4.10:9100\u0026quot;} - node_memory_MemAvailable_bytes{instance=\u0026quot;192.168.4.10:9100\u0026quot;}) / node_memory_MemTotal_bytes{instance=\u0026quot;192.168.4.10:9100\u0026quot;} * 100 Lalu Mengubah visualisasi menjadi “Gauge” dan menambahkan “Unit” dengan standar “Percent (0-100)”. Klik “Add Query” untuk menambahkan query :\n(node_memory_MemTotal_bytes{instance=\u0026quot;192.168.4.20:9100\u0026quot;} - node_memory_MemAvailable_bytes{instance=\u0026quot;192.168.4.20:9100\u0026quot;}) / node_memory_MemTotal_bytes{instance=\u0026quot;192.168.4.20:9100\u0026quot;} * 100\nKlik “Add Query” untuk menambahkan query :\n(node_memory_MemTotal_bytes{instance=\u0026quot;192.168.4.30:9100\u0026quot;} - node_memory_MemAvailable_bytes{instance=\u0026quot;192.168.4.30:9100\u0026quot;}) / node_memory_MemTotal_bytes{instance=\u0026quot;192.168.4.30:9100\u0026quot;} * 100 Lalu klik “Apply” untuk menerapkan setting. Selanjutnya membuat dashboard panel untuk menjawab pertanyaan “Berapa penggunaan disk pada tiap node?”.\nMenambahkan query :\n(node_filesystem_size_bytes{mountpoint=\u0026quot;/\u0026quot;,instance=\u0026quot;192.168.4.10:9100\u0026quot;} - node_filesystem_free_bytes{mountpoint=\u0026quot;/\u0026quot;,instance=\u0026quot;192.168.4.10:9100\u0026quot;}) / 1024 / 1024 / 1024 Lalu Mengubah visualisasi menjadi “Stat”, mengubah nama panel, dan mengubah “Color Mode”. Klik “Add Query” untuk menambahkan query :\n(node_filesystem_size_bytes{mountpoint=\u0026quot;/\u0026quot;,instance=\u0026quot;192.168.4.20:9100\u0026quot;} - node_filesystem_free_bytes{mountpoint=\u0026quot;/\u0026quot;,instance=\u0026quot;192.168.4.20:9100\u0026quot;}) / 1024 / 1024 / 1024 Lalu menambahkan “Unit” dengan standar “gigabytes”. Klik “Add Query” untuk menambahkan query :\n(node_filesystem_size_bytes{mountpoint=\u0026quot;/\u0026quot;,instance=\u0026quot;192.168.4.30:9100\u0026quot;} - node_filesystem_free_bytes{mountpoint=\u0026quot;/\u0026quot;,instance=\u0026quot;192.168.4.30:9100\u0026quot;}) / 1024 / 1024 / 1024 Lalu menghapus “Thresholds”, lalu klik “Apply”. Lalu jika sudah mengatur panel, bisa di klik tombol save. Dan isikan nama dashboard dan klik “Save”. Pengujian Prometheus dapat diakses pada URL https://192.168.4.10:9090 dan meminta input username dan password. Cek email yang terkirim jika ada firing status. Cek email yang terkirim jika ada resolve status. Cek email yang terkirim jika ada resolve dan firing status. Cek pesan di telegram yang terkirim jika ada firing status. Cek pesan di telegram yang terkirim jika ada resolve status. Kesimpulan Otomatisasi pada infrastruktur memungkinkan proses penskalaan menjadi lebih efisien. Bayangkan jika kita memiliki banyak node, konfigurasi manual akan menjadi tantangan besar. Inilah alasan kita menggunakan Ansible dan Terraform untuk mengelola infrastruktur secara otomatis. Selain itu, untuk memantau penggunaan, status, dan potensi masalah, diperlukan sistem monitoring dan deteksi anomali seperti Prometheus, Grafana, dan Alert Manager.\nReferensi Monitoring Docker dengan cAdvisor. https://prometheus.io/docs/guides/cadvisor/ Konfigurasi Alert Manager dan Template. https://prometheus.io/docs/alerting/latest/configuration/#telegram_config https://github.com/prometheus/alertmanager/issues/4076 https://gist.github.com/jidckii/5ac5f8f20368b56de72af70222509b7b https://github.com/prometheus/alertmanager/issues/1715 Ekspos Docker dengan protokol TCP. https://gist.github.com/styblope/dc55e0ad2a9848f2cc3307d4819d819f Instalasi Terraform. https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli#install-terraform Instalasi Grafana, Alert Manager, Prometheus. https://adinusa.id Basic Authentication dan SSL Self-signed Prometheus. https://medium.com/@abdullah.eid.2604/prometheus-security-c2652c32303d SSL Self-signed Grafana. https://grafana.com/docs/grafana/latest/setup-grafana/set-up-https/ Terraform Docker Provider. https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs Membuat app password untuk Gmail. https://support.google.com/mail/answer/185833?hl=en Membuat bot di Telegram. https://linuxtech.in/how-to-send-alerts-and-notifications-with-telegram/ ","permalink":"https://rifkyards.github.io/blogs/monitoring/monitoring-webapp-2/","summary":"\u003cp\u003eBlog ini merupakan kelanjutan dari bagian sebelumnya. Jika belum membacanya, bisa cek \u003ca href=\"https://rifkyards.github.io/blogs/monitoring/monitoring-webapp-1/\"\u003edisini\u003c/a\u003e.\u003c/p\u003e\n\u003ch1 id=\"langkah-implementasi\"\u003eLangkah Implementasi\u003c/h1\u003e\n\u003ch2 id=\"instalasi-dan-konfigurasi-tools-prometheus\"\u003eInstalasi dan Konfigurasi Tools Prometheus.\u003c/h2\u003e\n\u003cp\u003eNote : Lakukan langkah dibawah ini di monitoring node.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eDownload dan ekstrak file Prometheus.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e~$ sudo su -\n~# cd /opt\n/opt# wget\nhttps://github.com/prometheus/prometheus/releases/download/v2.48.1/prometheus-2.48.1.linux-amd64.tar.gz\n/opt# tar xvfz prometheus-2.48.1.linux-amd64.tar.gz\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003eMenambahkan file konfigurasi untuk Prometheus.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/opt# cd prometheus-2.48.1. linux-amd64\n/opt/prometheus-2.48.1. linux-amd64# vim config.yml\n\u003c/code\u003e\u003c/pre\u003e\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e---\nglobal:\n  scrape_interval:     10s\n  evaluation_interval: 15s\n\nscrape_configs:\n  - job_name: \u0026#39;node\u0026#39;\n    scrape_interval:  5s\n    static_configs:\n    - targets: [\u0026#39;192.168.4.10:9100\u0026#39;,\u0026#39;192.168.4.20:9100\u0026#39;,\u0026#39;192.168.4.30:9100\u0026#39;]\n\n  - job_name: \u0026#39;nginx\u0026#39;\n    static_configs:\n    - targets: [\u0026#39;192.168.4.20:9113\u0026#39;]\n\n  - job_name: \u0026#39;cadvisor\u0026#39;\n    static_configs:\n    - targets: [\u0026#39;192.168.4.30:8080\u0026#39;]\n\n  - job_name: \u0026#39;docker\u0026#39;\n    static_configs:\n    - targets: [\u0026#39;192.168.4.30:9323\u0026#39;]\n\nalerting:\n  alertmanagers:\n  - static_configs:\n    - targets:\n      - 192.168.4.10:9093\n\nrule_files:\n  - \u0026#34;rules/container.yml\u0026#34;\n  - \u0026#34;rules/node.yml\u0026#34;\n  - \u0026#34;rules/web-server.yml\u0026#34;\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003eMembuat SSL Key dan Certificate Signing Request.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/opt/prometheus-2.48.1.linux-amd64# sudo openssl genrsa -out /opt/prometheus-2.48.1.linux-amd64/prometheus.key 2048\n/opt/prometheus-2.48.1.linux-amd64# sudo openssl req -new -key /opt/prometheus-2.48.1.linux-amd64/prometheus.key -out /opt/prometheus-2.48.1.linux-amd64/prometheus.csr\n\u003c/code\u003e\u003c/pre\u003e\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eYou are about to be asked to enter information that will be incorporated\ninto your certificate request.\nWhat you are about to enter is what is called a Distinguished Name or a DN.\nThere are quite a few fields but you can leave some blank\nFor some fields there will be a default value,\nIf you enter \u0026#39;.\u0026#39;, the field will be left blank.\n\nCountry Name (2 letter code) [AU]:ID\nState or Province Name (full name) [Some-State]: South Kalimantan\nLocality Name (eg, city) []:Banjarbaru\nOrganization Name (eg, company) [Internet Widgits Pty Ltd]:\nOrganizational Unit Name (eg, section) []:\nCommon Name (e.g. server FQDN or YOUR name) []:\nEmail Address []:\n\nPlease enter the following \u0026#39;extra\u0026#39; attributes\nto be sent with your certificate request\nA challenge password []:\nAn optional company name []:\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003eMembuat SSL Self-Signed Certificate.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/opt/prometheus-2.48.1.linux-amd64# openssl x509 -req -days 365 -signkey prometheus.key -in prometheus.csr -out prometheus.crt -extfile \u0026lt;(echo \u0026#34;subjectAltName=IP:192.168.4.10\u0026#34; )\n\nCertificate request self-signature ok\nsubject=C = ID, ST = South Kalimantan, L = Banjarbaru, O = Internet Widgits Pty Ltd\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003eInstalasi paket yang dibutuhkan untuk basic authentication.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e~# sudo apt-get update \u0026amp;\u0026amp; sudo apt install apache2-utils -y\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003eMembuat password untuk basic authentication.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e~# htpasswd -nBC 12 \u0026#34;\u0026#34; | tr -d \u0026#39;:\\n\u0026#39;\nNew password: \u0026lt;inputYourPassword\u0026gt;\nRe-type new password: \u0026lt;inputYourPassword\u0026gt;\n\n$2y$12$\u0026lt;saltAndHash\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003eMenambahkan konfigurasi untuk web agar SSL dan basic authentication diterapkan.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/opt/prometheus-2.48.1. linux-amd64# vim web.yml\nbasic_auth_users:\nrifkyards: $2y$12$\u0026lt;saltAndHash\u0026gt;\ntls_server_config:\n    cert_file: /opt/prometheus-2.48.1.linux-amd64/prometheus.crt\n    key_file: /opt/prometheus-2.48.1.linux-amd64/prometheus.key\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003eMenambahkan rules untuk mengirimkan alert node yang mati ke Alert Manager.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/opt/prometheus-2.48.1.linux-amd64# vim rules/node.yml\n\u003c/code\u003e\u003c/pre\u003e\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# Add this lines\ngroups:\n  - name: NodeStatus\n    rules:\n      - alert: \u0026#34;NodeMonitoringDown\u0026#34;\n        expr: up{instance=\u0026#34;192.168.4.10:9100\u0026#34;} == 0\n        for: 5m\n        labels:\n          severity: critical\n          instance: \u0026#34;{{ $labels.instance }}\u0026#34;\n          alertname: \u0026#34;NodeMonitoringDown\u0026#34;\n        annotations:\n          title: \u0026#34;{{ $labels.instance }} is down\u0026#34;\n          description: \u0026#34;The server with IP {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34;\n\n      - alert: \u0026#34;NodeClient1Down\u0026#34;\n        expr: up{instance=\u0026#34;192.168.4.10:9100\u0026#34;} == 0\n        for: 5m\n        labels:\n          severity: critical\n          instance: \u0026#34;{{ $labels.instance }}\u0026#34;\n          alertname: NodeClient1Down\n        annotations:\n          title: \u0026#34;{{ $labels.name }} is down\u0026#34;\n          description: \u0026#34;The server with IP {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34;\n\n      - alert: \u0026#34;NodeClient2Down\u0026#34;\n        expr: up{instance=\u0026#34;192.168.4.30:9100\u0026#34;} == 0\n        for: 5m\n        labels:\n          severity: critical\n          instance: \u0026#34;{{ $labels.instance }}\u0026#34;\n          alertname: NodeClient2Down\n        annotations:\n          title: \u0026#34;{{ $labels.instance }} is down\u0026#34;\n          description: \u0026#34;The server with IP {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34;\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003eMenambahkan rules untuk mengirimkan alert Nginx Server yang mati ke Alert Manager.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/opt/prometheus-2.48.1.linux-amd64# vim rules/web-server.yml\n\u003c/code\u003e\u003c/pre\u003e\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# Add this lines\ngroups:\n  - name: WebNginxStatus\n    rules:\n      - alert: NginxDown\n        expr: nginx_up{instance=\u0026#34;192.168.4.20:9113\u0026#34;, job=\u0026#34;nginx\u0026#34;} == 0\n        for: 5m\n        labels:\n          severity: critical\n          instance: \u0026#34;{{ $labels.instance }}\u0026#34;\n          alertname: NginxDown\n        annotations:\n          title: \u0026#34;{{ $labels.name }} is down\u0026#34;\n          description: \u0026#34;The {{ $labels.job }} server on {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34;\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003eMenambahkan rules untuk mengirimkan alert container yang mati ke Alert Manager.\u003c/li\u003e\n\u003cli\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/opt/prometheus-2.48.1.linux-amd64# vim rules/container.yml\n\u003c/code\u003e\u003c/pre\u003e\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# Add this lines\ngroups:\n  - name: containerMonitoring\n    rules:\n      - alert: \u0026#34;Container2048Down\u0026#34;\n        expr: absent(container_start_time_seconds{name=\u0026#34;2048-apps\u0026#34;,instance=\u0026#34;192.168.4.30:8080\u0026#34;})\n        for: 5m\n        labels:\n          severity: critical\n          instance: \u0026#34;{{ $labels.instance }}\u0026#34;\n          alertname: Container2048Down\n        annotations:\n          title: \u0026#34;{{ $labels.name }} is down\u0026#34;\n          description: \u0026#34;The {{ $labels.name }} container on {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34;\n\n      - alert: \u0026#34;ContainerTicTacToeDown\u0026#34;\n        expr: absent(container_start_time_seconds{name=\u0026#34;tic-tac-toe-apps\u0026#34;,instance=\u0026#34;192.168.4.30:8080\u0026#34;})\n        for: 5m\n        labels:\n          severity: critical\n          instance: \u0026#34;{{ $labels.instance }}\u0026#34;\n          alertname: ContainerTicTacToeDown\n        annotations:\n          title: \u0026#34;{{ $labels.name }} is down\u0026#34;\n          description: \u0026#34;The {{ $labels.name }} container on {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34;\n\n      - alert: \u0026#34;GeneralContainerDown\u0026#34;\n        expr: time() - container_last_seen{instance=\u0026#34;192.168.4.30:8080\u0026#34;, image!=\u0026#34;\u0026#34;, name!~\u0026#34;2048-apps|tic-tac-toe-apps|cadvisor\u0026#34;} \u0026gt; 220\n        for: 20s\n        labels:\n          severity: critical\n          instance: \u0026#34;{{ $labels.instance }}\u0026#34;\n          alertname: GeneralContainerDown\n          resolved: \u0026#39;false\u0026#39;\n        annotations:\n          title: \u0026#34;{{ $labels.name }} is down\u0026#34;\n          description: \u0026#34;A container {{ $labels.name }} on {{ $labels.instance }} has been down for more than 5 minutes.\u0026#34;\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003eMenambahkan konfigurasi untuk Prometheus berjalan di SystemD.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e~# vim /etc/systemd/system/prometheus_server.service\n\u003c/code\u003e\u003c/pre\u003e\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# Add this lines\n[Unit]\nDescription=Prometheus Server\n\n[Service]\nUser=root\nExecStart=/opt/prometheus-2.48.1.linux-amd64/prometheus --config.file=/opt/prometheus-2.48.1.linux-amd64/config.yml --web.config.file=/opt/prometheus-2.48.1.linux-amd64/web.yml --web.external-url=https://192.168.4.10:9090/\n\n[Install]\nWantedBy=default.target\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003eMenjalankan perintah agar SystemD Prometheus berjalan.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e~# systemctl daemon-reload\n~# systemctl start prometheus_server\n~# systemctl enable prometheus_server\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"instalasi-dan-konfigurasi-tools-alert-manager\"\u003eInstalasi dan Konfigurasi Tools Alert Manager.\u003c/h2\u003e\n\u003cp\u003eNote : Lakukan langkah dibawah ini di monitoring node.\u003c/p\u003e","title":"[PART 2] Automated WebApp Provisioning and Secure Monitoring"},{"content":"Dalam lingkungan TI modern, banyak organisasi menghadapi tantangan dalam mengelola kombinasi aplikasi berbasis SystemD dan container. Kesulitan ini dapat menyebabkan kurangnya visibilitas terhadap performa sistem, meningkatkan risiko downtime yang tidak terdeteksi, dan menyulitkan tim dalam merespons masalah dengan cepat.\nUntuk mengatasi tantangan ini, pendekatan yang umum diterapkan adalah menetapkan satu server sebagai pusat monitoring dan kontrol otomatisasi. Server ini berperan dalam mengintegrasikan berbagai alat seperti Terraform untuk otomatisasi pembuatan infrastruktur berbasis container, serta Ansible untuk mengelola konfigurasi sistem, termasuk pengumpulan metrik dan pengelolaan aplikasi berbasis SystemD.\nDari sisi pemantauan, Prometheus digunakan untuk mengumpulkan data performa secara real-time, sementara Grafana menyediakan visualisasi yang jelas. Selain itu, Alertmanager memungkinkan pengiriman notifikasi melalui berbagai saluran komunikasi seperti email dan Telegram, sehingga tim dapat segera merespons potensi masalah sebelum berdampak lebih luas.\nPendekatan ini muncul dari kebutuhan mendesak untuk meningkatkan kontrol atas infrastruktur hybrid, memastikan stabilitas operasional, serta mendukung perubahan teknologi yang terus berkembang dengan lebih responsif dan efisien.\nTeori Apa itu Prometheus ? Sistem monitoring open-source yang digunakan untuk mengumpulkan metrics dari server atau aplikasi secara real-time. Data yang dikumpulkan dapat dianalisis dan dimanfaatkan untuk memahami performa sistem, serta menyediakan mekanisme peringatan jika terjadi anomali.\nApa itu Grafana ? Alat visualisasi data yang memungkinkan metrics ditampilkan dalam bentuk dashboard interaktif. Dengan Grafana, data yang dikumpulkan dari sistem monitoring seperti Prometheus dapat divisualisasikan dalam grafik yang lebih mudah dibaca dan dianalisis.\nApa itu Alert Manager? Komponen dalam ekosistem Prometheus yang bertanggung jawab mengelola notifikasi. Jika terjadi kondisi yang tidak diinginkan, seperti penggunaan CPU yang berlebihan atau server mengalami kegagalan, Alert Manager akan mengirimkan peringatan melalui berbagai platform komunikasi seperti email atau Telegram sesuai dengan aturan yang telah ditentukan.\nApa itu Terraform ? Alat yang digunakan untuk mengelola infrastruktur cloud menggunakan kode (Infrastructure as Code). Dengan Terraform, sumber daya seperti server, penyimpanan, dan jaringan dapat dikonfigurasi secara deklaratif, sehingga proses deployment menjadi lebih efisien dan terotomatisasi.\nApa itu Ansible ? Alat otomatisasi yang digunakan untuk mengelola konfigurasi server dan aplikasi. Dengan Ansible, kita bisa menjalankan perintah pada banyak server sekaligus, tanpa perlu mengaturnya satu per satu. Ansible menggunakan file YAML untuk mendefinisikan tugas-tugas yang harus dilakukan yang disebut dengan playbook.\nTools Ubuntu – Noble - v24.04 Prometheus – v2.48.1 Grafana – v10.2.2 Alert Manager – v0.26.0 Node Exporter – v1.7.0 Nginx – v1.24.0 Nginx Exporter – v1.4.1 Docker – v28.0.0 cAdvisor – v0.47.2 Python – v3.12.3 Ansible – v2.17.9 Terraform – v1.11.0 PHP – v8.1.31 Composer – v2.7.1 Gmail Telegram Topologi Alur Kerja Langkah Implementasi Konfigurasi Akses Remote Menggunakan SSH. Note : Lakukan langkah dibawah ini di semua node.\nUbah hostname pada semua node. Monitoring Node : ~$ sudo hostnamectl set-hostname server-monitoring Client1 Node : ~$ sudo hostnamectl set-hostname server-client1 Client2 Node : ~$ sudo hostnamectl set-hostname server-client2 Tambahkan name resolver secara lokal, sehingga sistem bisa mengenali hostname. ~$ sudo nano /etc/hosts # Add this line below 192.168.4.10 server-monitoring 192.168.4.20 server-client1 192.168.4.30 server-client2 Membuat SSH Key agar bisa melakukan akses ke Node lain secara passwordless. ~$ ssh-keygen -t rsa # Copying public key to other Node ~$ ssh-copy-id server-monitoring ~$ ssh-copy-id server-client1 ~$ ssh-copy-id server-client2 Instalasi Tools Ansible. Note : Lakukan langkah dibawah ini di monitoring node.\nMelakukan update paket dan instalasi Ansible. # Updating packages ~$ sudo apt update # Installing ansible ~$ sudo apt install -y software-properties-common ~$ sudo add-apt-repository --yes --update ppa:ansible/ansible ~$ sudo apt install ansible Memastikan bahwa Ansible sudah berhasil diinstall. ~$ ansible --version ansible [core 2.17.9] config file = /etc/ansible/ansible.cfg configured module search path = [\u0026#39;/home/student/.ansible/plugins/modules\u0026#39;, \u0026#39;/usr/share/ansible/plugins/modules\u0026#39;] ansible python module location = /usr/lib/python3/dist-packages/ansible ansible collection location = /home/student/.ansible/collections:/usr/share/ansible/collections executable location = /usr/bin/ansible python version = 3.12.3 (main, Feb 4 2025, 14:48:35) [GCC 13.3.0] (/usr/bin/python3) jinja version = 3.1.2 libyaml = True Instalasi Tools Terraform. Note : Lakukan langkah dibawah ini di monitoring node.\nMelakukan update paket dan instalasi paket yang dibutuhkan. ~$ sudo apt-get update \u0026amp;\u0026amp; sudo apt-get install -y gnupg software-properties-common Melakukan instalasi HashiCorp GPG key. ~$ wget -O- https://apt.releases.hashicorp.com/gpg | \\ gpg --dearmor | \\ sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg \u0026gt; /dev/null Melakukan verifikasi GPG Key fingerprint. ~$ gpg --no-default-keyring \\ --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg \\ --fingerprint Menambahkan repository HashiCorp dan instalasi Terraform. # Adding HashiCorp Repository ~$ echo \u0026#34;deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \\ https://apt.releases.hashicorp.com $(lsb_release -cs) main\u0026#34; | \\ sudo tee /etc/apt/sources.list.d/hashicorp.list # Updating packages and installing ~$ sudo apt update ~$ sudo apt-get install terraform Instalasi Node Exporter menggunakan Ansible. Note : Lakukan langkah dibawah ini di monitoring node.\nMenambahkan direktori untuk instalasi Node Exporter. ~$ mkdir ansible-node-exporter ~$ cd ~/ansible-node-exporter Menambahkan file ansible.cfg yang berisi konfigurasi yang akan dipakai oleh Ansible. ~/ansible-node-exporter$ vim ansible.cfg # Add this line below [defaults] inventory =. /inventory remote_user=student Menambahkan file inventory yang berisi list dari semua node. ~/ansible-node-exporter$ vim inventory # Add this line below server-monitoring server-client1 server-client2 Menambahkan file playbook untuk instalasi Node Exporter. ~/ansible-node-exporter$ vim setup-node-exporter.yml --- - name: Install Node Exporter and Set Up Systemd Service hosts: all become: yes vars: node_exporter_dir: \u0026#34;/opt/node_exporter\u0026#34; tasks: - name: Create the {{ node_exporter_dir }} directory file: path: \u0026#34;{{ node_exporter_dir }}\u0026#34; state: directory mode: \u0026#39;0755\u0026#39; - name: Download Node Exporter get_url: url: \u0026#34;https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz\u0026#34; dest: \u0026#34;{{ node_exporter_dir }}/node_exporter-1.7.0.linux-amd64.tar.gz\u0026#34; mode: \u0026#39;0644\u0026#39; - name: Extract Node Exporter using tar command: \u0026#34;tar -xzf {{ node_exporter_dir }}/node_exporter-1.7.0.linux-amd64.tar.gz -C {{ node_exporter_dir }}\u0026#34; - name: Remove the tarball after extraction file: path: \u0026#34;{{ node_exporter_dir }}/node_exporter-1.7.0.linux-amd64.tar.gz\u0026#34; state: absent - name: Make node_exporter executable file: path: \u0026#34;{{ node_exporter_dir }}/node_exporter-1.7.0.linux-amd64/node_exporter\u0026#34; mode: \u0026#39;0755\u0026#39; - name: Create systemd service for node_exporter copy: dest: /etc/systemd/system/node_exporter.service content: | [Unit] Description=Node Exporter After=network.target [Service] User=root ExecStart={{ node_exporter_dir }}/node_exporter-1.7.0.linux-amd64/node_exporter Restart=always [Install] WantedBy=multi-user.target mode: \u0026#39;0644\u0026#39; - name: Reload systemd daemon systemd: daemon_reload: yes - name: Enable and start node_exporter service systemd: name: node_exporter enabled: yes state: started - name: Verify node_exporter service status systemd: name: node_exporter state: started enabled: yes Menjalankan playbook agar instalasi Node Exporter dijalankan. ~/ansible-node-exporter$ ansible-playbook setup-node-exporter.yml Instalasi Docker menggunakan Ansible. Note : Lakukan langkah dibawah ini di monitoring node.\nMembuat direktori untuk instalasi Docker. ~$ mkdir ansible-docker ~$ cd ~/ansible-docker Menambahkan file ansible.cfg yang berisi konfigurasi yang akan dipakai oleh Ansible. ~/ansible-docker$ vim ansible.cfg # Add this line below [defaults] inventory =. /inventory remote_user=student Menambahkan file inventory yang berisi list dari node yang akan diinstal Docker. ~/ansible-docker$ vim inventory # Add this line below [docker_host] server-client2 Menambahkan file playbook untuk instalasi Docker. ~/ansible-docker$ vim setup-docker.yml --- - name: Setup Docker with Custom Configuration hosts: docker_host become: yes vars: docker_daemon_config: hosts: [\u0026#34;tcp://0.0.0.0:2375\u0026#34;, \u0026#34;unix:///var/run/docker.sock\u0026#34;] experimental: true metrics_addr: \u0026#34;192.168.4.30:9323\u0026#34; override_config: exec_start: \u0026#34;/usr/bin/dockerd\u0026#34; tasks: - name: Install required packages apt: name: - ca-certificates - curl state: present update_cache: yes - name: Create /etc/apt/keyrings if it does not exist file: path: /etc/apt/keyrings state: directory mode: \u0026#39;0755\u0026#39; - name: Download Docker GPG key get_url: url: https://download.docker.com/linux/ubuntu/gpg dest: /etc/apt/keyrings/docker.asc mode: \u0026#39;0644\u0026#39; - name: Configure Docker APT repository blockinfile: path: /etc/apt/sources.list.d/docker.list block: | deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release | lower }} stable - name: Update apt cache apt: update_cache: yes - name: Install Docker apt: name: - docker-ce - docker-ce-cli - containerd.io - docker-buildx-plugin - docker-compose-plugin state: present - name: Add docker group if it does not exist group: name: docker state: present - name: Add user to docker group user: name: \u0026#34;{{ ansible_user }}\u0026#34; groups: docker append: yes - name: Create Docker daemon.json file copy: dest: /etc/docker/daemon.json content: | { \u0026#34;hosts\u0026#34;: {{ docker_daemon_config.hosts | to_json }}, \u0026#34;experimental\u0026#34;: {{ docker_daemon_config.experimental }}, \u0026#34;metrics-addr\u0026#34;: \u0026#34;{{ docker_daemon_config.metrics_addr }}\u0026#34; } owner: root group: root mode: \u0026#39;0644\u0026#39; - name: Create Docker systemd override directory file: path: /etc/systemd/system/docker.service.d state: directory mode: \u0026#39;0755\u0026#39; - name: Create Docker systemd override file copy: dest: /etc/systemd/system/docker.service.d/override.conf content: | [Service] ExecStart= ExecStart={{ override_config.exec_start }} owner: root group: root mode: \u0026#39;0644\u0026#39; - name: Reload systemd to apply Docker configuration systemd: daemon_reload: yes - name: Restart Docker service systemd: name: docker state: restarted enabled: yes - name: Verify Docker service status systemd: name: docker state: started enabled: yes Menjalankan playbook untuk instalasi Docker. ~/ansible-docker$ ansible-playbook setup-docker.yml Deploy Aplikasi Web Laravel dan Nginx Exporter menggunakan Ansible. Note : Lakukan langkah dibawah ini di monitoring node.\nMembuat direktori untuk deploy aplikasi web Laravel dan Nginx Exporter. ~$ mkdir ansible-laragigs ~$ cd ansible-laragigs Membuat Ansible roles dan ansible.cfg. ~/ansible-laragigs$ ansible-galaxy init laragigs ~/ansible-laragigs$ vim ansible.cfg # Add this line below [defaults] inventory =. /inventory remote_user=student Menambahkan file inventory yang berisi list dari node yang akan diinstal aplikasi web. ~/ansible-laragigs$ vim inventory # Add this line below [webapp] server-client1 Menambahkan task untuk install paket dan dependensi. ~/ansible-laragigs$ vim laragigs/tasks/install.yml - name: Install software-properties-common apt: name: software-properties-common state: present - name: Add PPA for PHP from Ondrej shell: | sudo add-apt-repository -y ppa:ondrej/php become: yes - name: Update apt cache apt: update_cache: yes force_apt_get: yes - name: Install required packages apt: name: \u0026#34;{{ item }}\u0026#34; state: present loop: \u0026#34;{{ packages }}\u0026#34; Menambahkan task untuk konfigurasi dan instalasi database MySQL. ~/ansible-laragigs$ vim laragigs/tasks/database.yml - name: Install required packages apt: name: mysql-server state: present - name: Create MySQL database and user command: \u0026gt; mysql -u root -e \u0026#34;CREATE DATABASE IF NOT EXISTS {{ db_database }}; CREATE USER IF NOT EXISTS \u0026#39;{{ db_username }}\u0026#39;@\u0026#39;localhost\u0026#39; IDENTIFIED BY \u0026#39;{{ db_password }}\u0026#39;; GRANT ALL PRIVILEGES ON {{ db_database }}.* TO \u0026#39;{{ db_username }}\u0026#39;@\u0026#39;localhost\u0026#39;;\u0026#34; Menambahkan task untuk konfigurasi dan deployment aplikasi web Laravel dan Nginx. ~/ansible-laragigs$ vim laragigs/tasks/configure.yml - name: Git Clone Laravel become: false git: repo: https://github.com/bradtraversy/laragigs.git dest: \u0026#34;{{ remote_dir }}\u0026#34; force: true - name: Install Laravel Dependencies become: false composer: command: install arguments: \u0026#34;--no-dev --optimize-autoloader\u0026#34; working_dir: \u0026#34;{{ remote_dir }}\u0026#34; - name: Configure env for the app become: false template: src: env.j2 dest: \u0026#34;{{ remote_dir }}/.env\u0026#34; - name: Generate application key become: false command: php artisan key:generate args: chdir: \u0026#34;{{ remote_dir }}\u0026#34; - name: Migrate database become: false command: php artisan migrate args: chdir: \u0026#34;{{ remote_dir }}\u0026#34; - name: Move from remote directory to app directory shell: mv \u0026#34;{{ remote_dir }}/\u0026#34; \u0026#34;{{ app_dir }}\u0026#34; - name: Change permission for laragigs app file: path: \u0026#34;{{ app_dir }}\u0026#34; owner: www-data group: www-data recurse: yes - name: Set permissions to 755 for /var/www/laragigs file: path: \u0026#34;{{ app_dir }}\u0026#34; mode: \u0026#39;0755\u0026#39; recurse: yes - name: Creating a symbolic link for storage command: sudo php artisan storage:link args: chdir: \u0026#34;{{ app_dir }}\u0026#34; - name: Configure laragigs host template: src: laragigs.j2 dest: \u0026#34;{{ nginx_dir }}/sites-available/laragigs\u0026#34; - name: Create a symbolic link from sites-available to sites-enabled file: src: \u0026#34;{{ nginx_dir }}/sites-available/laragigs\u0026#34; dest: \u0026#34;{{ nginx_dir }}/sites-enabled/laragigs\u0026#34; state: link - name: Remove {{ nginx_dir }}/sites-enabled/default file: path: \u0026#34;{{ nginx_dir }}/sites-enabled/default\u0026#34; state: absent - name: Restart Nginx systemd: name: nginx state: restarted Menambahkan task untuk instalasi dan konfigurasi Nginx Exporter. ~/ansible-laragigs$ vim laragigs/tasks/exporter.yml - name: Create the {{ nginx_exporter_dir }} directory file: path: \u0026#34;{{ nginx_exporter_dir }}\u0026#34; state: directory mode: \u0026#39;0755\u0026#39; - name: Download Nginx Prometheus Exporter get_url: url: \u0026#34;https://github.com/nginx/nginx-prometheus-exporter/releases/download/v1.4.1/nginx-prometheus-exporter_1.4.1_linux_amd64.tar.gz\u0026#34; dest: \u0026#34;{{ nginx_exporter_dir }}/nginx-prometheus-exporter_1.4.1_linux_amd64.tar.gz\u0026#34; mode: \u0026#39;0644\u0026#39; - name: Extract Nginx Prometheus Exporter using tar command: \u0026#34;tar -xzf {{ nginx_exporter_dir }}/nginx-prometheus-exporter_1.4.1_linux_amd64.tar.gz -C {{ nginx_exporter_dir }}\u0026#34; - name: Remove the tarball after extraction file: path: \u0026#34;{{ nginx_exporter_dir }}/nginx-prometheus-exporter_1.4.1_linux_amd64.tar.gz\u0026#34; state: absent - name: Make nginx-prometheus-exporter executable file: path: \u0026#34;{{ nginx_exporter_dir }}/nginx-prometheus-exporter\u0026#34; mode: \u0026#39;0755\u0026#39; - name: Configure Apache for Laravel template: src: nginx_exporter.j2 dest: /etc/systemd/system/nginx_exporter.service - name: Reload systemd daemon systemd: daemon_reload: yes - name: Enable and start nginx_exporter service systemd: name: nginx_exporter enabled: yes state: started Menambahkan task yang mengurutkan langkah dijalankannya task yang udah dibuat. ~/ansible-laragigs$ vim laragigs/tasks/main.yml --- # tasks file for laragigs - name: Include installation tasks include_tasks: install.yml - name: Setup database when: ansible_play_hosts | length == 1 include_tasks: database.yml - name: Check if /var/www/laragigs exists stat: path: /var/www/laragigs register: laragigs_dir - name: Running configure, skip setup if /var/www/laragigs exists when: laragigs_dir.stat.exists == false include_tasks: configure.yml - name: Setup nginx exporter include_tasks: exporter.yml Menambahkan variable yang akan digunakan oleh task yang udah dibuat. ~/ansible-laragigs$ mkdir laragigs/vars/main ~/ansible-laragigs$ mv laragigs/vars/main.yml laragigs/vars/main ~/ansible-laragigs$ vim laragigs/vars/main/main.yml --- # vars file for laragigs packages: - php8.1 - php8.1-fpm - php8.1-mysql - php8.1-mbstring - php8.1-xml - php8.1-zip - php8.1-curl - php8.1-common - php8.1-intl - git - nginx - composer db_username: laragigs_user db_database: laragigs remote_dir: /home/student/laragigs app_dir: /var/www/laragigs nginx_dir: /etc/nginx nginx_exporter_dir: /opt/nginx_exporter Menambahkan vault untuk menyimpan variable yang terjaga. ~/ansible-laragigs$ ansible-vault create laragigs/vars/main/secrets.yml New Vault password: \u0026lt;inputVaultPass\u0026gt; Confirm New Vault password: \u0026lt;inputVaultPass\u0026gt; # Add this lines after input a password db_password: \u0026#34;\u0026lt;yourDBPass\u0026gt;\u0026#34; Menambahkan file template untuk environment variable yang akan dipakai aplikasi web. ~/ansible-laragigs$ vim laragigs/templates/env.j2 APP_NAME=Laravel APP_ENV=local APP_KEY= APP_DEBUG=true APP_URL=http://localhost LOG_CHANNEL=stack LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=\u0026#34;{{ db_database }}\u0026#34; DB_USERNAME=\u0026#34;{{ db_username }}\u0026#34; DB_PASSWORD=\u0026#34;{{ db_password }}\u0026#34; BROADCAST_DRIVER=log CACHE_DRIVER=file FILESYSTEM_DISK=local QUEUE_CONNECTION=sync SESSION_DRIVER=file SESSION_LIFETIME=120 MEMCACHED_HOST=127.0.0.1 REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 MAIL_MAILER=smtp MAIL_HOST=mailhog MAIL_PORT=1025 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS=\u0026#34;hello@example.com\u0026#34; MAIL_FROM_NAME=\u0026#34;${APP_NAME}\u0026#34; AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET= AWS_USE_PATH_STYLE_ENDPOINT=false PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= PUSHER_APP_CLUSTER=mt1 MIX_PUSHER_APP_KEY=\u0026#34;${PUSHER_APP_KEY}\u0026#34; MIX_PUSHER_APP_CLUSTER=\u0026#34;${PUSHER_APP_CLUSTER}\u0026#34; Menambahkan file template untuk konfigurasi Nginx. ~/ansible-laragigs$ vim laragigs/templates/laragigs.j2 server { listen 80; server_name _; root {{ app_dir }}/public; index index.php index.html index.htm; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \\.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.1-fpm.sock; # Sesuaikan dengan versi PHP fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~ /\\.(?!well-known).* { deny all; } location ~* \\.(jpg|jpeg|png|gif|ico|css|js)$ { expires 365d; log_not_found off; } location /nginx/status { stub_status; allow 127.0.0.1; deny all; } error_log /var/log/nginx/laragigs_error.log; access_log /var/log/nginx/laragigs_access.log; } Menambahkan file template untuk konfigurasi Nginx Exporter. ~/ansible-laragigs$ vim laragigs/templates/node_exporter.j2 [Unit] Description=Nginx Exporter [Service] User=root ExecStart={{ nginx_exporter_dir }}/nginx-prometheus-exporter --nginx.scrape-uri=http://127.0.0.1/nginx/status [Install] WantedBy=default.target Menambahkan playbook yang berisi tasks dari Ansible roles. ~/ansible-laragigs$ vim main.yml - name: Use role playbook hosts: webapp become: true pre_tasks: - name: pre_tasks message debug: msg: \u0026#39;Prepare to deploying laragigs app.\u0026#39; roles: - laragigs post_tasks: - name: post_tasks message debug: msg: \u0026#39;Laragigs app is deployed!\u0026#39; Semua file template, tasks, dan lainnya sudah dibuat. Lalu jalankan playbook. ~/ansible-laragigs$ ansible-playbook main.yml --ask-vault-pass Vault password: \u0026lt;inputVaultPass\u0026gt; Deploy Aplikasi Web berbasis Container menggunakan Terraform. Membuat direktori untuk aplikasi web berbasis container. ~$ mkdir terraform-docker-apps ~$ cd terraform-docker-apps Menambahkan Docker sebagai provider. ~/terraform-docker-apps$ vim provider.tf terraform { required_providers { docker = { source = \u0026#34;kreuzwerker/docker\u0026#34; version = \u0026#34;3.0.2\u0026#34; } } } provider \u0026#34;docker\u0026#34; { host = \u0026#34;tcp://192.168.4.30:2375\u0026#34; } Membuat file untuk membuat Docker image ~/terraform-docker-apps$ vim image.tf # Pull cAdvisor image resource \u0026#34;docker_image\u0026#34; \u0026#34;image-cadvisor\u0026#34; { name = \u0026#34;gcr.io/cadvisor/cadvisor:latest\u0026#34; } # Build 2048-apps image resource \u0026#34;docker_image\u0026#34; \u0026#34;image-2048\u0026#34; { name = \u0026#34;2048-apps\u0026#34; build { context = \u0026#34;2048-apps\u0026#34; dockerfile = \u0026#34;Dockerfile\u0026#34; } } # Build tic-tac-toe-apps image resource \u0026#34;docker_image\u0026#34; \u0026#34;image-tic-tac-toe\u0026#34; { name = \u0026#34;tic-tac-toe-apps\u0026#34; build { context = \u0026#34;tic-tac-toe-apps\u0026#34; dockerfile = \u0026#34;Dockerfile\u0026#34; } } # Pull Busybox image resource \u0026#34;docker_image\u0026#34; \u0026#34;image-busybox\u0026#34; { name = \u0026#34;busybox:latest\u0026#34; } Menambahkan file untuk membuat Docker container ~/terraform-docker-apps$ vim main.tf # Run cAdvisor container resource \u0026#34;docker_container\u0026#34; \u0026#34;container-cadvisor\u0026#34; { name = \u0026#34;cadvisor\u0026#34; image = docker_image.image-cadvisor.image_id ports { internal = 8080 external = 8080 } depends_on = [ docker_container.container-2048, docker_container.container-tic-tac-toe, docker_container.container-down-apps-1, docker_container.container-down-apps-2, docker_container.container-down-apps-3, docker_container.container-down-apps-4 ] volumes { container_path = \u0026#34;/rootfs\u0026#34; host_path = \u0026#34;/\u0026#34; read_only = true } volumes { container_path = \u0026#34;/var/run\u0026#34; host_path = \u0026#34;/var/run\u0026#34; } volumes { container_path = \u0026#34;/sys\u0026#34; host_path = \u0026#34;/sys\u0026#34; read_only = true } volumes { container_path = \u0026#34;/var/lib/docker/\u0026#34; host_path = \u0026#34;/var/lib/docker\u0026#34; read_only = true } } resource \u0026#34;docker_container\u0026#34; \u0026#34;container-2048\u0026#34; { name = \u0026#34;2048-apps\u0026#34; image = docker_image.image-2048.image_id ports { internal = 80 external = 8081 } } resource \u0026#34;docker_container\u0026#34; \u0026#34;container-tic-tac-toe\u0026#34; { name = \u0026#34;tic-tac-toe-apps\u0026#34; image = docker_image.image-tic-tac-toe.image_id ports { internal = 80 external = 8082 } } resource \u0026#34;docker_container\u0026#34; \u0026#34;container-down-apps-1\u0026#34; { name = \u0026#34;down-apps-1\u0026#34; image = docker_image.image-busybox.image_id command = [\u0026#34;/bin/sh\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;echo \u0026#39;This container will run for 1 hour\u0026#39; \u0026amp;\u0026amp; sleep 900\u0026#34;] } resource \u0026#34;docker_container\u0026#34; \u0026#34;container-down-apps-2\u0026#34; { name = \u0026#34;down-apps-2\u0026#34; image = docker_image.image-busybox.image_id command = [\u0026#34;/bin/sh\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;echo \u0026#39;This container will run for 1 hour\u0026#39; \u0026amp;\u0026amp; sleep 900\u0026#34;] } resource \u0026#34;docker_container\u0026#34; \u0026#34;container-down-apps-3\u0026#34; { name = \u0026#34;down-apps-3\u0026#34; image = docker_image.image-busybox.image_id command = [\u0026#34;/bin/sh\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;echo \u0026#39;This container will run for 1 hour\u0026#39; \u0026amp;\u0026amp; sleep 900\u0026#34;] } resource \u0026#34;docker_container\u0026#34; \u0026#34;container-down-apps-4\u0026#34; { name = \u0026#34;down-apps-4\u0026#34; image = docker_image.image-busybox.image_id command = [\u0026#34;/bin/sh\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;echo \u0026#39;This container will run for 1 hour\u0026#39; \u0026amp;\u0026amp; sleep 900\u0026#34;] } Download source code dari aplikasi web 2048. ~/terraform-docker-apps$ mkdir 2048-apps ~/terraform-docker-apps$ cd 2048-apps ~/terraform-docker-apps/2048-apps$ mkdir app ~/terraform-docker-apps/2048-apps$ git clone https://github.com/gabrielecirulli/2048.git app Membuat Dockerfile untuk aplikasi web 2048. ~/terraform-docker-apps/2048-apps$ vim Dockerfile # Add this lines FROM httpd:alpine COPY ./app/ /usr/local/apache2/htdocs/ EXPOSE 80 Download source code dari aplikasi web TicTacToe. ~/terraform-docker-apps$ mkdir tic-tac-toe-apps ~/terraform-docker-apps$ cd tic-tac-toe-apps ~/terraform-docker-apps/tic-tac-toe-apps$ mkdir app ~/terraform-docker-apps/tic-tac-toe-apps$ git clone https://github.com/Aklilu-Mandefro/javascript-Tic-Tac-Toe-game-app.git app Membuat Dockerfile untuk aplikasi web TicTacToe. ~/terraform-docker-apps/tic-tac-toe-apps$ vim Dockerfile # Add this lines FROM nginx:alpine COPY ./app/ /usr/share/nginx/html/ EXPOSE 80 Mengelola dan menerapkan konfigurasi dengan Terraform. ~/terraform-docker-apps$ terraform init ~/terraform-docker-apps$ terraform fmt ~/terraform-docker-apps$ terraform plan ~/terraform-docker-apps$ terraform apply --auto-approve Untuk part selanjutnya bisa klik disini.\n","permalink":"https://rifkyards.github.io/blogs/monitoring/monitoring-webapp-1/","summary":"\u003cp\u003eDalam lingkungan TI modern, banyak organisasi menghadapi tantangan dalam mengelola kombinasi aplikasi berbasis \u003cstrong\u003eSystemD\u003c/strong\u003e dan \u003cstrong\u003econtainer\u003c/strong\u003e. Kesulitan ini dapat menyebabkan kurangnya visibilitas terhadap performa sistem, meningkatkan risiko downtime yang tidak terdeteksi, dan menyulitkan tim dalam merespons masalah dengan cepat.\u003c/p\u003e\n\u003cp\u003eUntuk mengatasi tantangan ini, pendekatan yang umum diterapkan adalah menetapkan satu server sebagai \u003cstrong\u003epusat monitoring dan kontrol otomatisasi\u003c/strong\u003e. Server ini berperan dalam mengintegrasikan berbagai alat seperti \u003cstrong\u003eTerraform\u003c/strong\u003e untuk otomatisasi pembuatan infrastruktur berbasis container, serta \u003cstrong\u003eAnsible\u003c/strong\u003e untuk mengelola konfigurasi sistem, termasuk pengumpulan metrik dan pengelolaan aplikasi berbasis SystemD.\u003c/p\u003e","title":"[PART 1] Automated WebApp Provisioning and Secure Monitoring"},{"content":"Pada blog sebelumnya tentang Deploying Openstack with OpenStack-Ansible, telah dibahas bagaimana OpenStack memungkinkan pengelolaan banyak server secara otomatis dan efisien, sehingga menciptakan infrastruktur cloud yang lebih stabil dan mudah dikembangkan.\nNamun, untuk pengelolaan biaya dan tagihan terkait penggunaan sumber daya OpenStack, dibutuhkan sebuah solusi tambahan yang memudahkan pemantauan dan perhitungan biaya. Yuyu Billing hadir sebagai plug-in untuk OpenStack yang memungkinkan pengelolaan tagihan secara otomatis dan efisien. Dengan Yuyu, Anda dapat menghitung biaya untuk berbagai fitur OpenStack, seperti instance flavors, volumes, floating IPs, routers, snapshots, dan images, sehingga memudahkan pengelolaan anggaran dan memastikan transparansi biaya dalam lingkungan cloud.\nTeori Apa itu Horizon? Horizon adalah dashboard berbasis web untuk OpenStack yang memungkinkan pengguna mengelola layanan OpenStack melalui antarmuka grafis. Dengan Horizon, pengguna dapat mengelola instance, jaringan, penyimpanan, dan sumber daya lainnya tanpa perlu menggunakan CLI atau API secara langsung.\nApa itu Yuyu Billing? Yuyu merupakan plug-in untuk OpenStack yang memudahkan pengelolaan tagihan dengan memungkinkan pengguna untuk menghitung biaya berbagai fitur OpenStack, seperti Instance Flavors, Volumes, Floating IPs, Routers, Snapshots, dan Images. Plugin ini membantu pengguna mengelola biaya terkait penggunaan sumber daya di OpenStack secara lebih efisien.\nTools Ubuntu – Jammy – v22.04 OpenStack – Caracal – v2024.1 OpenStack-Ansible – v2024.1 Python – v3.10.12 Ansible - v2.15.9 Horizon – v23.4.0 Heat Dashboard – v11.0.0 Yuyu API \u0026amp; Event Monitor – Last updated on Oct 2, 2023 Yuyu Dashboard – Last updated on Dec 10, 2023 Django – v3.2 Python-Memcached – v1.59 Topologi Langkah Implementasi 1. Deploy Horizon Sebagai Halaman Dashboard dari Openstack Note : Lakukan langkah dibawah ini di controller node.\nMelakukan update paket dan instalasi paket beserta dependensi yang dibutuhkan oleh horizon. # Update package ~# apt update -y # Install package and dependencies ~# apt install python3 python3-dev python3-venv python3-distutils apache2 libapache2-mod-wsgi-py3 libmemcached-tools python3-setuptools python3-virtualenv python3-pip -y Download file-file yang dibutuhkan oleh Horizon. ~# cd /var/www/html/ /var/www/html# git clone -b 23.4.0 https://opendev.org/openstack/horizon.git Melakukan instalasi depedensi dan library yang dibutuhkan oleh Horizon. /var/www/html# cd horizon /var/www/html/horizon# pip install -U pip /var/www/html/horizon# wget https://opendev.org/openstack/requirements/raw/branch/stable/2024.1/upper-constraints.txt /var/www/html/horizon# sed -i \u0026#39;s/horizon===\\([0-9.]\\+\\)/horizon===23.4.0/g\u0026#39; upper-constraints.txt /var/www/html/horizon# pip install -c upper-constraints.txt . /var/www/html/horizon# pip install -r requirements.txt /var/www/html/horizon# pip install \u0026#34;Django\u0026gt;=3.2,\u0026lt;3.3\u0026#34; --upgrade /var/www/html/horizon# pip install --upgrade --force-reinstall python-memcached==1.59 Menyalin file template konfigurasi Horizon. Dan menambahkan konfigurasi untuk Horizon. /var/www/html/horizon# cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py /var/www/html/horizon# nano openstack_dashboard/local/local_settings.py DEBUG = True WEBROOT = \u0026#34;/\u0026#34; ALLOWED_HOSTS = [\u0026#39;*\u0026#39;] #Yuyu Configs YUYU_URL = \u0026#34;http://192.168.4.10:8182\u0026#34; CURRENCIES = (\u0026#39;IDR\u0026#39;,) DEFAULT_CURRENCY = \u0026#34;IDR\u0026#34; CACHES = { \u0026#39;default\u0026#39;: { \u0026#39;BACKEND\u0026#39;: \u0026#39;django.core.cache.backends.memcached.MemcachedCache\u0026#39;, \u0026#39;LOCATION\u0026#39;: \u0026#39;\u0026lt;IP dari Memcached Container\u0026gt;:11211\u0026#39;, }, } OPENSTACK_KEYSTONE_URL = \u0026#34;http://192.168.4.10:5000/v3\u0026#34; OPENSTACK_KEYSTONE_DOMAIN_CHOICES = ( (\u0026#39;Default\u0026#39;, \u0026#39;default\u0026#39; ) ) OPENSTACK_KEYSTONE_BACKEND = { \u0026#39;name\u0026#39;: \u0026#39;native\u0026#39;, \u0026#39;can_edit_group\u0026#39;: True, \u0026#39;can_edit_user\u0026#39;: True, \u0026#39;can_edit_role\u0026#39;: True, \u0026#39;can_edit_project\u0026#39;: True, \u0026#39;can_edit_domain\u0026#39;: True, } AVAILABLE_THEMES = [ (\u0026#39;default\u0026#39;, \u0026#39;Default\u0026#39;, \u0026#39;themes/default\u0026#39;), (\u0026#39;material\u0026#39;, \u0026#39;Material\u0026#39;, \u0026#39;themes/material\u0026#39; ), (\u0026#39;example\u0026#39;, \u0026#39;Example\u0026#39;, \u0026#39;themes/example\u0026#39; ) ] Untuk mendapatkan IP dari Memcached, bisa dengan perintah di bawah. Gunakan IP dari management network. ~# lxc-ls -f | grep \u0026#34;memcached\u0026#34; pod-controller-memcached-container-46f8dbab RUNNING 1 onboot, openstack 10.0.3.226, 192.168.4.183 - false Mendownload paket halaman dahsboard untuk service Heat. Lalu menyalin konfigurasi dari paket tersebut ke Horizon. ~# pip install heat-dashboard==11.0.0 ~# cp -n /usr/local/lib/python3.10/dist-packages/heat_dashboard/enabled/_[1-9]*.py /var/www/html/horizon/openstack_dashboard/enabled/ Menjalankan perintah untuk ntuk mengumpulkan dan memindahkan file statis (seperti CSS, JavaScript, gambar). /var/www/html/horizon# ./manage.py collectstatic Menjalankan perintah agar aplikasi Django Horizon bisa dijalankan dengan WSGI (untuk menghubungkan aplikasi Python dengan server web) dan Apache sebagai server web untuk melayani aplikasi tersebut. /var/www/html/horizon# ./manage.py make_web_conf --wsgi /var/www/html/horizon# ./manage.py make_web_conf --apache \u0026gt; /etc/apache2/sites-available/horizon.conf Menjalankan perintah untuk mengonfigurasi Apache untuk menggunakan situs horizon.conf dan menonaktifkan situs default, serta mengubah konfigurasi HAProxy. ~# a2ensite horizon.conf \u0026amp;\u0026amp; a2dissite 000-default.conf ~# nano /etc/haproxy/haproxy.cfg ## Add comment for frontend that listen to port 80 ## #frontend base-front-1 # bind 192.168.4.10:80 # option httplog # option forwardfor except 127.0.0.0/8 # use_backend %[path, map_reg(/etc/haproxy/base_regex.map)] # mode http Menjalankan perintah untuk mengubah kepemilikan dan izin akses file untuk Horizon agar bisa digunakan oleh Apache. /var/www/html/horizon# chown -R www-data:www-data openstack_dashboard/local/.secret_key_store /var/www/html/horizon# chown -R www-data:www-data static/ /var/www/html/horizon# chmod a+x openstack_dashboard/wsgi.py 2. Konfigurasi Yuyu Billing API, Event Monitor dan Dashboard Note : Lakukan langkah dibawah ini di controller node.\nMelihat nama dari container yang dibuat oleh Openstack-Ansible. ~# lxc-ls pod-controller-cinder-api-container-09654180 pod-controller-galera-container-6bcebebb pod-controller-glance-container-b31353e2 pod-controller-heat-api-container-aec695b2 pod-controller-keystone-container-aa059c5b pod-controller-memcached-container-46f8dbab pod-controller-neutron-server-container-3335ac4f pod-controller-nova-api-container-57ed6068 pod-controller-placement-container-806005d7 pod-controller-rabbit-mq-container-fa6b4b03 pod-controller-repo-container-45f85cad pod-controller-utility-container-ebab4dfe Menjalankan perintah untuk mendapatkan password dari RabbitMQ. ~# cat /etc/openstack_deploy/user_secrets.yml | grep rabbitmq_monitoring_password rabbitmq_monitoring_password: \u0026lt;Monitoring Password\u0026gt; Mendapatkan IP dari container RabbitMQ, serta konfigurasi user monitoring agar memiliki akses baca pada semua data di RabbitMQ. Disini kita akan memakai IP yang berasal dari management network. ~# lxc-ls -f | grep rabbit pod-controller-rabbit-mq-container-fa6b4b03 RUNNING 1 onboot, openstack 10.0.3.137, 192.168.4.182 - false ~# lxc-attach pod-controller-rabbit-mq-container-fa6b4b03 rabbit-mq:/# rabbitmqctl set_permissions -p / monitoring \u0026#34;.*\u0026#34; \u0026#34;.*\u0026#34; \u0026#34;.*\u0026#34; Menambahkan konfigurasi agar service Nova mengirimkan data ke RabbitMQ yang akan digunakan oleh Yuyu /# lxc-attach \u0026lt;Nova Container\u0026gt; nova:/# apt install nano nova:/# nano /etc/nova/nova.conf # Modify this group configs [oslo_messaging_notifications] driver = messagingv2 topics = notifications transport_url = rabbit://monitoring:\u0026lt;Monitoring Password\u0026gt;@\u0026lt;RabbitMQ IP\u0026gt;:5672/ #Also add this [notifications] notify_on_state_change = vm_and_task_state notification_format = unversioned nova:/# systemctl restart nova-scheduler Menambahkan konfigurasi agar service Cinder mengirimkan data ke RabbitMQ yang akan digunakan oleh Yuyu. /# lxc-attach \u0026lt;Cinder Container\u0026gt; cinder:/# apt install nano cinder:/# nano /etc/cinder/cinder.conf # Modify this group configs [oslo_messaging_notifications] driver = messagingv2 topics = notifications transport_url = rabbit://monitoring:\u0026lt;Monitoring Password\u0026gt;@\u0026lt;RabbitMQ IP\u0026gt;:5672/ cinder:/# systemctl restart cinder-scheduler Menambahkan konfigurasi agar service Neutron mengirimkan data ke RabbitMQ yang akan digunakan oleh Yuyu. /# lxc-attach \u0026lt;Neutron Container\u0026gt; neutron:/# apt install nano neutron:/# nano /etc/neutron/neutron.conf # Modify this group configs [oslo_messaging_notifications] driver = messagingv2 topics = notifications transport_url = rabbit://monitoring:\u0026lt;Monitoring Password\u0026gt;@\u0026lt;RabbitMQ IP\u0026gt;:5672/ neutron:/# systemctl restart neutron-server Menambahkan konfigurasi agar service Keystone mengirimkan data ke RabbitMQ yang akan digunakan oleh Yuyu. /# lxc-attach \u0026lt;Keystone Container\u0026gt; keystone:/# apt install nano keystone:/# nano /etc/keystone/keystone. conf # Modify this group configs [oslo_messaging_notifications] driver = messagingv2 topics = notifications transport_url = rabbit://monitoring:\u0026lt;Monitoring Password\u0026gt;@\u0026lt;RabbitMQ IP\u0026gt;:5672/ keystone:/# systemctl restart keystone-wsgi-public Download file-file yang dibutuhkan oleh Yuyu, dan mendownload depedensi dan library yang dibutuhkan. ~# cd /var/ ~# git clone https://github.com/Yuyu-billing/yuyu.git ~# cd yuyu /var/yuyu# virtualenv env /var/yuyu# source env/bin/activate (env): /var/yuyu# pip install -r requirements.txt Menambahkan konfigurasi untuk koneksi ke RabbitMQ dan Email yang akan dipakai. (env):/var/yuyu# cp yuyu/local_settings.py.sample yuyu/local_settings.py (env):/var/yuyu# vi yuyu/local_settings.py YUYU_NOTIFICATION_URL = \u0026#34;rabbit://monitoring:\u0026lt;RabbitMQ Pass\u0026gt;@\u0026lt;RabbitMQ IP\u0026gt;:5672//\u0026#34; YUYU_NOTIFICATION_TOPICS = [\u0026#34;notifications\u0026#34;] # Currency Configuration CURRENCIES = (\u0026#39;IDR\u0026#39;,) DEFAULT_CURRENCY = \u0026#34;IDR\u0026#34; # Email Setting EMAIL_TAG = \u0026#39;[YUYU]\u0026#39; DEFAULT_FROM_EMAIL = \u0026#39;no-reply@btech.id\u0026#39; EMAIL_BACKEND = \u0026#39;django.core.mail.backends.smtp. EmailBackend\u0026#39; EMAIL_HOST = \u0026#39;smtp.gmail.com\u0026#39; EMAIL_HOST_USER = \u0026#39;\u0026lt;paste your gmail account here\u0026gt;\u0026#39; EMAIL_HOST_PASSWORD = \u0026#39;\u0026lt;paste Google password or app password here\u0026gt;\u0026#39; EMAIL_PORT = 587 EMAIL_USE_TLS = True Memodifikasi konfigurasi pada Yuyu agar menjalankan dan menerima request dari IP Controller. (env):/var/yuyu# nano script/yuyu_api.service # Change IP in this line ExecStart={{yuyu_dir}}/env/bin/gunicorn yuyu.wsgi --workers 2 --bind 192.168.4.10:8182 --log-file=logs/gunicorn.log (env):/var/yuyu# nano yuyu/settings.py # Add IP in this line ALLOWED_HOSTS = [\u0026#34;192.168.4.10\u0026#34;] Menjalankan skrip untuk instalasi Yuyu API. (env):/var/yuyu# ./bin/setup_api.sh (env):/var/yuyu# systemctl enable yuyu_api (env):/var/yuyu# systemctl start yuyu_api (env):/var/yuyu# systemctl status yuyu_api Menjalankan skrip untuk instalasi Yuyu Event Monitor. (env):/var/yuyu# ./bin/setup_event_monitor.sh (env):/var/yuyu# systemctl enable yuyu_event_monitor (env):/var/yuyu# systemctl start yuyu_event_monitor (env):/var/yuyu# systemctl status yuyu_event_monitor Konfigurasi crontab agar skrip pengiriman invoice dijalankan setiap bulannya. (env):/var/yuyu# crontab -e #Add this line 1 0 1 * * /var/yuyu/bin/process_invoice.sh (env):/var/yuyu# deactivate Download file-file yang dibutuhkan oleh Yuyu Dashboard. /var/yuyu# cd /var/ /var/yuyu# git clone https://github.com/Yuyu-billing/yuyu_dashboard.git /var/yuyu# cd yuyu_dashboard Menjalankan skrip untuk instalasi Yuyu Dashboard. /var/yuyu_dashboard# ./setup_yuyu.sh Specify Horizon Location (ex: /etc/horizon): /var/www/html/horizon /var/yuyu_dashboard# pip3 install -r requirements.txt Menjalankan perintah untuk restart HAProxy, Apache2, dan Memcached. ~# systemctl restart haproxy apache2 ~# lxc-ls | grep \u0026#34;memcached\u0026#34; pod-controller-memcached-container-46f8dbab ~# lxc-attach pod-controller-memcached-container-46f8dbab systemctl restart memcached 3. Setting Yuyu Billing melalui Dashboard Mendapatkan password dari user admin Note : Lakukan langkah dibawah ini di controller node. ~# cat /etc/openstack_deploy/user_secrets.yml | grep keystone_auth_admin keystone_auth_admin_password: \u0026lt;Password\u0026gt; Akses Dashboard OpenStack dengan mengakses IP dari Controller. Untuk pengaturan Yuyu Billing bisa ikuti langkah-langkah berikut :\nPengaturan harga melalui panel “Admin” \u0026gt; “Billing” \u0026gt; “Price Configuration”. Pengaturan informasi mengenai perusahaan melalui panel “Admin” \u0026gt; “Billing” \u0026gt; “Billing Setting” \u0026gt; “Update Setting”. Setelah mengisi informasi harga dan perusahaan, baru menyalakan Billing Setting. Pengujian Mencoba akses panel “Admin” \u0026gt; “Billing” \u0026gt; “Billing Overview”. Pastikan data yang ditampilkan sesuai dengan resource OpenStack yang sudah terpakai. Referensi Penjelasan mengenai Yuyu Billing. https://yuyu-billing.dev/introduction/ Deploy Horizon secara manual. https://vianaja.github.io/blog-najwan/2024-12-02-secure-openstack-horizon-yuyu/ https://docs.openstack.org/horizon/latest/install/install-ubuntu.html https://docs.openstack.org/releasenotes/horizon/2024.1.html Deploy Heat Dashboard secara manual. https://docs.openstack.org/heat-dashboard/latest/install/index.html Deploy Yuyu Billing. https://yuyu-billing.dev/pre-installation/ https://yuyu-billing.dev/installation/ ","permalink":"https://rifkyards.github.io/blogs/openstack/horizon-with-yuyu/","summary":"\u003cp\u003ePada blog sebelumnya tentang \u003ca href=\"https://rifkyards.github.io/blogs/openstack/openstack-ansible/\"\u003eDeploying Openstack with OpenStack-Ansible\u003c/a\u003e, telah dibahas bagaimana OpenStack memungkinkan pengelolaan banyak server secara otomatis dan efisien, sehingga menciptakan infrastruktur cloud yang lebih stabil dan mudah dikembangkan.\u003c/p\u003e\n\u003cp\u003eNamun, untuk pengelolaan biaya dan tagihan terkait penggunaan sumber daya OpenStack, dibutuhkan sebuah solusi tambahan yang memudahkan pemantauan dan perhitungan biaya. \u003cstrong\u003eYuyu Billing\u003c/strong\u003e hadir sebagai plug-in untuk OpenStack yang memungkinkan pengelolaan tagihan secara otomatis dan efisien. Dengan \u003cstrong\u003eYuyu\u003c/strong\u003e, Anda dapat menghitung biaya untuk berbagai fitur OpenStack, seperti instance flavors, volumes, floating IPs, routers, snapshots, dan images, sehingga memudahkan pengelolaan anggaran dan memastikan transparansi biaya dalam lingkungan cloud.\u003c/p\u003e","title":"Using Horizon and Yuyu to Track Your OpenStack Resource"},{"content":"Saat ini, pengelolaan banyak server secara manual sangat tidak efisien dan memerlukan waktu yang lama. Jika salah satu server mengalami gangguan, sistem dapat terganggu, dan proses penambahan server baru juga cukup rumit. Solusi yang dapat diterapkan adalah menggunakan OpenStack, yang menggabungkan seluruh server menjadi satu sistem cloud agar lebih fleksibel dan mudah dikelola. Untuk memastikan proses ini berjalan otomatis dan efisien, digunakan OpenStack-Ansible, yang memungkinkan konfigurasi sistem dilakukan tanpa perlu pengaturan manual satu per satu. Dengan solusi ini, infrastruktur menjadi lebih stabil, mudah dikembangkan, dan lebih andal dalam menghadapi gangguan.\nTeori Apa itu Openstack? Openstack adalah platform komputasi awan (cloud computing) open-source yang memungkinkan kita untuk membangun dan mengelola infrastruktur cloud publik maupun private. Bayangkan OpenStack sebagai sistem operasi untuk seluruh pusat data. Dengan OpenStack, kita dapat mengontrol dan mengelola sumber daya komputasi, penyimpanan, dan jaringan melalui antarmuka yang terstandarisasi. OpenStack sendiri memiliki banyak service, yang memiliki fungsi berbeda-beda. Untuk Informasi lebih lanjut mengenai service OpenStack, bisa baca disini.\nApa itu Ansible? Ansible merupakan alat otomatisasi yang digunakan untuk mengelola konfigurasi server dan aplikasi. Dengan Ansible, kita bisa menjalankan perintah pada banyak server sekaligus, tanpa perlu mengaturnya satu per satu. Ansible menggunakan file YAML untuk mendefinisikan tugas-tugas yang harus dilakukan yang disebut dengan playbook.\nApa itu Openstack-Ansible? Openstack-Ansible adalah sebuah proyek yang menggabungkan OpenStack dan Ansible untuk mempermudah instalasi serta manajemen OpenStack secara otomatis. Pengguna dapat menginstal dan mengelola berbagai komponen OpenStack menggunakan Playbook Ansible, yang membuat deployment lebih konsisten dan dapat diskalakan. Dalam implementasinya, OpenStack dapat dijalankan dalam container untuk meningkatkan isolasi dan manajemen sumber daya.\nTools Ubuntu – Jammy – v22.04 OpenStack – Caracal – v2024.1 OpenStack-Ansible – v2024.1 Python – v3.10.12 Ansible - v2.15.9 Topologi Jaringan Logikal Langkah Implementasi 1. Konfigurasi Port Bridge Note : Lakukan langkah dibawah ini di semua node.\nMenambahkan interface bridge ”br-mgmt” yang nantinya akan dipakai sebagai management interface untuk container. ~$ sudo nano /etc/netplan/50-cloud-init.yaml network: version: 2 ethernets: ens3: dhcp4: false ens4: dhcp4: false bridges: br-mgmt: interfaces: [ens3] addresses: [\u0026lt;NodeIP\u0026gt;/24] routes: - to: default via: 192.168.4.1 nameservers: addresses: [8.8.8.8] parameters: stp: false forward-delay: 0 Terapkan konfigurasi yang sudah kita definisikan ~$ sudo netplan apply 2. Konfigurasi Akses Remote menggunakan SSH Note : Lakukan langkah dibawah ini di semua node.\nUbah hostname pada semua node. Controller Node : ~$ sudo hostnamectl set-hostname pod-controller Compute1 Node : ~$ sudo hostnamectl set-hostname pod-compute1 Compute2 Node : ~$ sudo hostnamectl set-hostname pod-compute2 Tambahkan name resolver secara lokal, sehingga sistem bisa mengenali hostname tanpa bergantung pada DNS eksternal. ~$ sudo nano /etc/hosts # Add this line below 192.168.4.10 pod-controller 192.168.4.20 pod-compute1 192.168.4.30 pod-compute2 Membuat SSH Key agar bisa melakukan akses ke Node lain secara passwordless. ~$ ssh-keygen -t rsa # Copying public key to other Node ~$ ssh-copy-id pod-controller ~$ ssh-copy-id pod-compute1 ~$ ssh-copy-id pod-compute2 Mengubah password dari user root. ~$ sudo -i ~# passwd root Membuat SSH Key untuk user root. Note : Lakukan langkah dibawah ini di controller node. ~# ssh-keygen -t rsa # Copying public key to other Node ~# ssh-copy-id pod-controller ~# ssh-copy-id pod-compute1 ~# ssh-copy-id pod-compute2 3. Deploy OpenStack dengan OpenStack-Ansible Note : Lakukan langkah dibawah ini di semua node.\nMemperbarui paket dan install depedensi yang dibutuhkan. # Updating packages ~$ sudo apt update -y # Installing dependecies ~$ sudo apt install build-essential git chrony openssh-server python3-dev sudo bridge-utils debootstrap openssh-server tcpdump vlan python3 -y Membuat physical volume dan volume group untuk penyimpan data-data dari service Cinder. ~# pvcreate /dev/vdb ~# vgcreate cinder-volumes /dev/vdb Note : Lakukan langkah dibawah ini di controller node. Membuat file untuk swap. ~$ sudo fallocate -l 8G /swapfile ~$ sudo chmod 600 /swapfile ~$ sudo mkswap / swapfile ~$ sudo swapon /swapfile ~$ sudo vim /etc/fstab # Add this line below /swapfile swap swap defaults 0 0 Download paket OpenStack-Ansible. # Change to root user ~$ sudo -i # Clone openstack-ansible package ~# git clone -b stable/2024.1 https://opendev.org/openstack/openstack-ansible /opt/openstack-ansible Jalankan skrip bootstrap agar ansible dan paket-paket terkait terinstall. ~# cd /opt/openstack-ansible /opt/openstack-ansible# scripts/bootstrap-ansible.sh Menyalin template konfigurasi ke direktori “/etc/openstack_deploy”. Dan konfigurasi file utama, yaitu “openstack_user_config.yml”. ~# cp -avrp /opt/openstack-ansible/etc/openstack_deploy /etc/. ~# cd /etc/openstack_deploy/ /etc/openstack_deploy# nano openstack_user_config.yml --- cidr_networks: container: 192.168.4.0/24 used_ips: - \u0026#34;192.168.4.0,192.168.4.10,192.168.4.20,192.168.4.30\u0026#34; global_overrides: internal_lb_vip_address: 192.168.4.10 external_lb_vip_address: 192.168.4.10 management_bridge: \u0026#34;br-mgmt\u0026#34; provider_networks: - network: group_binds: - all_containers - hosts type: \u0026#34;raw\u0026#34; container_bridge: \u0026#34;br-mgmt\u0026#34; container_interface: \u0026#34;eth1\u0026#34; container_type: \u0026#34;veth\u0026#34; ip_from_q: \u0026#34;container\u0026#34; is_container_address: true is_ssh_address: true is_management_address: true controller: \u0026amp;controllers pod-controller: ip: 192.168.4.10 compute: \u0026amp;computes pod-compute1: ip: 192.168.4.20 pod-compute2: ip: 192.168.4.30 shared-infra_hosts: *controllers repo-infra_hosts: *controllers image_hosts: *controllers orchestration_hosts: *controllers placement-infra_hosts: *controllers identity_hosts: *controllers network_hosts: *controllers compute-infra_hosts: *controllers compute_hosts: *computes haproxy_hosts: *controllers storage-infra_hosts: *controllers storage_hosts: pod-controller: ip: 192.168.4.10 container_vars: cinder_storage_availability_zone: cinderAZ_1 cinder_default_availability_zone: cinderAZ_1 cinder_backends: lvm: volume_backend_name: LVM_iSCSI volume_driver: cinder.volume.drivers.lvm.LVMVolumeDriver volume_group: cinder-volumes iscsi_ip_address: \u0026#34;{{ cinder_storage_address }}\u0026#34; limit_container_types: cinder_volume pod-compute1: ip: 192.168.4.20 container_vars: cinder_storage_availability_zone: cinderAZ_1 cinder_default_availability_zone: cinderAZ_1 cinder_backends: lvm: volume_backend_name: LVM_iSCSI volume_driver: cinder.volume.drivers.lvm.LVMVolumeDriver volume_group: cinder-volumes iscsi_ip_address: \u0026#34;{{ cinder_storage_address }}\u0026#34; limit_container_types: cinder_volume pod-compute2: ip: 192.168.4.30 container_vars: cinder_storage_availability_zone: cinderAZ_1 cinder_default_availability_zone: cinderAZ_1 cinder_backends: lvm: volume_backend_name: LVM_iSCSI volume_driver: cinder.volume.drivers.lvm.LVMVolumeDriver volume_group: cinder-volumes iscsi_ip_address: \u0026#34;{{ cinder_storage_address }}\u0026#34; limit_container_types: cinder_volume Konfigurasi file “user_variables.yml” untuk menentukan variabel kustom yang akan diterapkan dalam deployment OpenStack-Ansible. /etc/openstack_deploy# nano user_variables.yml apply_security_hardening: false # SSL Configs haproxy_ssl: false horizon_enable_ssl: false openstack_external_ssl: false # Neutron Configs neutron_plugin_type: \u0026#34;ml2.ovs\u0026#34; neutron_provider_networks: network_flat_networks: \u0026#34;provider\u0026#34; network_mappings: \u0026#34;provider:br-ex\u0026#34; network_interface_mappings: \u0026#34;br-ex:ens4\u0026#34; network_types: \u0026#34;vxlan\u0026#34; network_vxlan_ranges: \u0026#34;1:1000\u0026#34; neutron_ml2_drivers_type: \u0026#34;flat,vlan,vxlan\u0026#34; neutron_plugin_base: - router neutron_l2_population: True neutron_ml2_mechanism_drivers: \u0026#34;openvswitch,l2population\u0026#34; neutron_firewall_driver: \u0026#34;iptables_hybrid\u0026#34; # Galera Configs galera_cluster_name: openstack_galera_cluster galera_max_connections: 3200 # Nova Configs openstack_service_publicuri_proto: \u0026#34;http\u0026#34; nova_console_type: novnc # Heat Configs heat_wsgi_processes: 1 heat_api_threads: 1 heat_engine_workers: 1 # RabbitMQ Configs rabbitmq_use_ssl: False rabbitmq_queue_replication: False oslomsg_rabbit_quorum_queues: False rabbitmq_monitoring_userid: monitoring rabbitmq_upgrade: false rabbitmq_erlang_extra_args: \u0026#34;+sbwt none +sbwtdcpu none +sbwtdio none +stbt nnts\u0026#34; Menjalankan skrip yang akan membuat password dari service dan komponen OpenStack. ~# cd /opt/openstack-ansible /opt/openstack-ansible# ./scripts/pw-token-gen.py --file /etc/openstack_deploy/user_secrets.yml Menjalankan playbook agar service dan komponen dari OpenStack terinstall. ~# cd /opt/openstack-ansible/playbooks/ /opt/openstack-ansible/playbooks# openstack-ansible setup-hosts.yml /opt/openstack-ansible/playbooks# openstack-ansible setup-infrastructure.yml /opt/openstack-ansible/playbooks# openstack-ansible setup-openstack.yml Pengujian Akses container utility, dan menggunakan identitas OpenStack dengan file “openrc”. ~# lxc-ls | grep \u0026#34;utility\u0026#34; pod-controller-utility-container-ebab4dfe ~# lxc-attach pod-controller-utility-container-ebab4dfe utility:/# source /root/openrc Install wget untuk download image cirros. Lalu menambahkan image Cirros ke OpenStack. utility:/# apt install wget -y utility:/# wget http://download.cirros-cloud.net/0.6.2/cirros-0.6.2-x86_64-disk.img utility:/# openstack image create --disk-format qcow2 --container-format bare --public --file ./cirros-0.62-x86_64-disk.img cirros-0.6.2-rifky Menambahkan jaringan eksternal untuk OpenStack. utility:/# openstack network create --share --external --provider-physical-network provider --provider-network-type flat external-net-rifky utility:/# openstack subnet create --network external-net-rifky --gateway 20.6.6.1 --no-dhcp --subnet-range 20.6.6.0/24 external-subnet-rifky Menambahkan jaringan internal untuk OpenStack. utility:/# openstack network create internal-net-rifky utility:/# openstack subnet create --network internal-net-rifky --allocation-pool start=192.168.6.10, end=192.168.6.254 --dns-nameserver 8.8.8.8 --gateway 192.168.6.1 --subnet-range 192.168.6.0/24 internal-subnet-rifky Menambahkan router pada OpenStack, yang akan menghubungkan jaringan internal dan eksternal. utility:/# openstack router create router-rifky utility:/# openstack router set --external-gateway external-net-rifky router-rifky utility:/# openstack router add subnet router-rifky internal-subnet-rifky Membuat security group yang didefinisikan agar bisa diakses secara SSH, dan bisa di ping. utility:/# openstack security group create security-group-rifky --description \u0026#39;Allow SSH and ICMP\u0026#39; utility:/# openstack security group rule create --protocol icmp security-group-rifky utility:/# openstack security group rule create --protocol tcp --ingress --dst-port 22 security-group-rifky Membuat keypair yang akan digunakan untuk mengakses instance tanpa menggunakan password. utility:/# exit ~# cat /root/.ssh/id_rsa.pub ssh-rsa xxxxx root@pod-controller ~# lxc-attach pod-controller-utility-container-ebab4dfe utility:/# echo \u0026#34;ssh-rsa xxxxx root@pod-controller\u0026#34; \u0026gt; id_rsa.pub utility:/# source /root/openrc utility:/# openstack keypair create --public-key id_rsa.pub controller-key Membuat flavor untuk mendefinisikan spesifikasi yang bisa dipakai oleh instance. utility:/# openstack flavor create --ram 512 --disk 5 --vcpus 1 --public c2-small Membuat instance dengan resource yang sudah kita buat sebelumnya. Dan menambahkan floating IP, agar bisa diakses dari jaringan eksternal. utility:/# openstack server create --flavor c2-small --image cirros-0.6.2-rifky --key-name controller-key --security-group security-group-rifky --network internal-net-rifky cirros-instance-rifky utility:/# openstack floating ip create --floating-ip-address 20.6.6.200 external-net-rifky utility:/# openstack server add floating ip cirros-instance-rifky 20.6.6.200 Pengujian akses internet dari instance Cirros. $ cat /etc/os-release PRETTY_NAME=\u0026#34;CirrOS 0.6.2\u0026#34; NAME=\u0026#34;CirrOS\u0026#34; VERSION_ID=\u0026#34;0.6.2\u0026#34; ID=cirros HOME_URL=\u0026#34;https://cirros-cloud.net\u0026#34; BUG_REPORT_URL=\u0026#34;https://github.com/cirros-dev/cirros/issues\u0026#34; $ ping google.com PING 216.58.199.238 (216.58.199.238) 56(84) bytes of data. 64 bytes from kix05s02-in-f238.1e100.net (216.58.199.238): icmp_seq=1 ttl=119 time=1.69 ms 64 bytes from kul09s15-in-f14.le100.net (216.58.199.238): icmp_seq=2 ttl=119 time=2.31 ms --- 216.58.199.238 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 1.687/1.997/2.308/0.310 ms Pengujian ping dan akses SSH ke arah floating IP dari instance Cirros. controller:/# ping 20.6.6.200 PING 20.6.6.200 (20.6.6.200) 56(84) bytes of data. 64 bytes from 20.6.6.200: icmp_seq=1 ttl=62 time=3.53 ms 64 bytes from 20.6.6.200: icmp_seq=2 ttl=62 time=1.97 ms --- 20.6.6.200 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 1.965/2.745/3.526/0.780 ms controller:/# ssh -o \u0026#39;PubkeyAcceptedKeyTypes +ssh-rsa\u0026#39; cirros@20.6.6.200 $ cat /etc/os-release PRETTY_NAME=\u0026#34;CirrOS 0.6.2\u0026#34; NAME=\u0026#34;CirrOS\u0026#34; VERSION_ID=\u0026#34;0.6.2\u0026#34; ID=cirros HOME_URL=\u0026#34;https://cirros-cloud.net\u0026#34; BUG_REPORT_URL=\u0026#34;https://github.com/cirros-dev/cirros/issues\u0026#34; Referensi Penjelasan mengenai Cloud Computing. https://btech.id/id/news/what-is-cloud-computing/ Penjelasan mengenai OpenStack. https://btech.id/en/news/mengenal-openstack-serta-fitur-dan-kelebihannya/ Deploy Openstack menggunakan Openstack-Ansible. https://docs.openstack.org/project-deploy-guide/openstack-ansible/2024.1/ Konfigurasi Openstack-Ansible. https://docs.openstack.org/openstack-ansible/latest/reference/inventory/openstack-user-config-reference.html https://satishdotpatel.github.io/build-openstack-cloud-using-openstack-ansible/ https://satishdotpatel.github.io/openstack-ansible-multinode-ovn/ https://medium.com/@travistruman/configuring-openstack-ansible-for-open-vswitch-b7e70e26009d ","permalink":"https://rifkyards.github.io/blogs/openstack/openstack-ansible/","summary":"\u003cp\u003eSaat ini, pengelolaan banyak server secara manual sangat tidak efisien dan memerlukan waktu yang lama. Jika salah satu server mengalami gangguan, sistem dapat terganggu, dan proses penambahan server baru juga cukup rumit. Solusi yang dapat diterapkan adalah menggunakan \u003cstrong\u003eOpenStack\u003c/strong\u003e, yang menggabungkan seluruh server menjadi satu sistem cloud agar lebih fleksibel dan mudah dikelola. Untuk memastikan proses ini berjalan otomatis dan efisien, digunakan \u003cstrong\u003eOpenStack-Ansible\u003c/strong\u003e, yang memungkinkan konfigurasi sistem dilakukan tanpa perlu pengaturan manual satu per satu. Dengan solusi ini, infrastruktur menjadi lebih stabil, mudah dikembangkan, dan lebih andal dalam menghadapi gangguan.\u003c/p\u003e","title":"Deploying OpenStack with Openstack-Ansible"}]