Tag: kubernetes

  • Data Gravity Will Remain an Issue

    Data Gravity Will Remain an Issue

    Things are improving for IT at a rate we haven’t seen since the first wave of container adoption. We have massive automation in the entire SDLC—with AI-based plug-ins for IDEs to help developers write code that is both higher quality and more secure, security deeply integrated into the DevOps toolchain and the unification of testing/security tools across the SDLC. We are once again turning out more code of higher quality faster than we were just a year ago.

    And what is finally starting to catch up is data. I love the current iteration of data virtualization technology, where it can be set to move from region to region or cloud to cloud at leisure in the background. At the same time, data that is accessed in the interim can be instantly transferred. I used to cover storage and data, and frankly, this is the dream world.

    But it doesn’t change the fact that data location matters. While bulk moving data to its final destination will be useful, separating data from applications that access it is simply adding another weak link in the application infrastructure chain.

    This is where the true strength of containers and Kubernetes come in. With Kubernetes, we can put containers with the entirety of our apps into the environment where our data resides. And that means that our application infrastructure is consolidated and that, in a pinch, both application and data can be moved anywhere–because Kubernetes is truly portable (as long as you don’t use customization features of some vendors/platforms anyway).

    The environments we currently choose to use for enterprise applications–from mainframe to public cloud and everything in between–all are capable of running containers, and while there are still deployment differences, customizing a bit to move an entire application is far better than rewriting entire apps to target a new host environment. And the amount of retargeting required is constantly going down.

    So, decide where you would like to host your solution, use data virtualization to move the datasets there, spin up your apps in Kubernetes at that location and enjoy the fruits of your labors. Mergers, acquisitions, moves from one architecture to another, moving from public cloud vendor A to public cloud vendor B … All made far easier by data and Kubernetes portability.

    While people like to call it “cloud,” what we really should be calling it is “portable.” Whichever marketing person decided that cloud included Kubernetes is my sworn enemy, btw. Because the cloud is used without including Kubernetes, so of course, that just confuses the issue. Portable programming is a far better description of data mobility and Kubernetes architecture used in tandem. Doesn’t need a cloud at all.

    And we’re headed there for even more productivity. Just pick where to move it and carry on. We do indeed live in pretty cool times, and you all are the ones making it real. Keep up the good work.

    Image source: https://vecteezy_businessman-holding-social-planet-showing-networking-skills_1268342.jpg

     

     

  • Improvement Cycles and AI

    Improvement Cycles and AI

    It’s that time of year when pundits start to crank out their predictions for the next twelve months! I’ve been asked to contribute to a private group (and occasionally, Techstrong Group asks me to contribute to their annual list), so I won’t thrill you with my predictions just yet; but I will discuss the cycles and trends that previous predictions have shown.

    Back when I was testing physical servers, we thought of throughput bottlenecks in terms of where the problem was. The circle would go disk->memory-> CPU, and in the case of things like NAS, insert network in there somewhere, too. When one bottleneck was resolved, another would crop up. And users will always seem to be pushed to the next bottleneck.

    We see similar cycles in DevOps. First, Agile made development faster, and that caused us issues throughout the rest of the process. Then, DevOps helped with the build and a little with the testing and deployment steps, but in the early days it was more standardization than speeding up. And since then, we have been in that cycle. We’re seeing GitOps speed up and automate deployment and upgrades—based upon the automation that came before—we’re seeing test and security tools feeding directly into the IDE to speed resolution, we’re seeing container automation cause “cloud-first development” (I hate that name; Kubernetes has cloud-like interfaces, but is not precisely cloud) to be fully automated, and thus faster.

    And we’re looking at that cycle continuing. No doubt you will hear a lot of predictions that start with “AI …” For the most part, AI is a tool and/or technique. Listen for what it is improving because it is doing very little that’s actually new. (Delete list of things that sounded alarmingly like those predictions I said I wouldn’t make.)

    All in all, we are still living in a very cool technological time. We can have a tool generate code snippets of the dull work for us so we can focus on the important bits. Some shy away from this use of “AI,” but honestly, we already use libraries to do the grunt work—I haven’t written to a screen buffer in forever—because we don’t have to. Same story—use the tools that make you productive. Some of the more obscure bits of Linux command lines are far better dealt with by asking an AI to give me examples than searching through tons of docs across several platforms. Never was much of a fan of man output for complex commands, this makes it easier. The nice bit is that bash and UNIX utilities don’t change much over time, so answers can be a bit dated and perfectly accurate. That’s not true for much of IT.

    The environment has consistently gotten more complex, while the building blocks have gotten easier to use. This allows things to keep moving and changing while it offers us better ways to serve the organization’s needs. This does change at some point—infinite change is indeed a thing, but any technology does have its limits—but I honestly can’t see the point at which we are content with our IT tools and stop looking for more. Oh, most organizations go through those cycles—organizationally, once an infrastructure and process works correctly, it is likely to hang around until better is found—but the industry will keep changing.

    And you’ll keep learning and changing. That’s one prediction I will make for next year. Teams and IT staff will grow and learn new things, because at its heart, that is what we do. We learn new things and keep the lights on. In good years, we offer sweet new tools and functionality to the company or our customers. But either way, we keep things online. Year after year. You all rock, so that’s an easy prediction.

  • How to Alleviate Your Observability Challenges

    How to Alleviate Your Observability Challenges

    Observability is becoming a keystone of contemporary DevOps practices. Even departments that weren’t traditionally a part of DevOps are seeing the benefits of being brought under the auspices of observability teams. In 2023, however, organizations are finding that the road to adoption is bumpier than expected. Here are seven of the biggest challenges DevOps teams face with observability and some suggestions for mitigating them.

    Increasing MTTR

    MTTR, or mean time to recovery, is the time it takes to get a system back up and running after an outage or bug. A longer MTTR means more downtime and poorer service for clients. Worryingly, the DevOps Pulse Report indicates that the average MTTR is increasing. This year, 73% of its respondents reported an MTTR of multiple hours; last year’s figure was only 64%.

    MTTR often results from an inability to diagnose incidents due to data siloes impairing observability. This can be improved by an observability platform that allows engineers to see the big picture.

    Costs of Telemetry Data

    Along with increasing MTTR, many organizations have to deal with costs incurred by high telemetry data volumes. It’s a big problem. An IDC survey of 200 companies found that 53% of respondents highlighted the costs of storing log data.

    Much of the problem is due to an outmoded tiered pricing model. Many vendors charge per GB of data, so if your data volumes fluctuate, so will your data costs. They also have obscure pricing models, meaning many organizations find it difficult to know what they’re paying for. At Coralogix, we’ve created a new business model that is one-third of the cost of standard log storage solutions.

    Tool Sprawl

    To understand why this is a challenge, we need to answer the question: What is observability? Effective observability requires integrating data from every aspect of your application. Because many organizations implement monitoring with multiple tools, they suffer from tool sprawl. This has the effect of siloing telemetry data, making it harder to correlate data and extract insights into system performance.

    There are a range of options for mitigating tool sprawl, such as thoroughly evaluating a tool’s costs and benefits before including it in your DevOps strategy. The most effective solution is a “single pane of glass” tool that combines insights synoptically on a single dashboard.

    Kubernetes Complexity

    Elastic reports that organizations are increasingly turning to cloud-based solutions such as Kubernetes for their DevOps. Kubernetes can supercharge organizations with its ability to dynamically scale infrastructure as needed, eliminating the cost overheads of dedicated servers.

    However, Kubernetes is complex and comes with its own set of challenges. Kubernetes’ scalable architecture comes from containerization, a paradigm in which applications are hosted in objects called containers. This means that developing in Kubernetes requires the ability to work with a lot of spinning plates.

    A good way to combat this is better training in organizations. Additionally, breaking down silos allows different teams to transfer knowledge.

    Security Challenges

    Kubernetes’ popularity brings security challenges. These can include privilege escalation, where a user manages to gain privileges such as write access, and security misconfigurations, where developers forget to change the non-secure default configurations.

    There are several strategies for mitigating Kubernetes security risks. These include scoping roles to particular namespaces, using service meshes, and enhancing security with Coralogix’s Kubernetes Operator.

    Beyond Kubernetes, there’s the larger issue of integrating security into an observability strategy, which is becoming a challenge for an increasing number of IT businesses. To counter this, more and more businesses are starting to incorporate observability and security monitoring under a single umbrella. Solutions such as infrastructure and application metrics can enhance security and monitoring.

    Scaling Platforms

    To meet the challenges posed by rising data costs and increasing cloud complexity, businesses are turning to open-source solutions. These come with their own challenges, however. According to the DevOps Pulse Report, around 30% of enterprises surveyed had problems with infrastructure management, scaling and upgrading relevant components. Because many open-source platforms require specialized knowledge to maintain, businesses have trouble sourcing the skills and expertise for them.

    Tools such as OpenTelemetry can make scaling easier by integrating with platforms such as Coralogix.

    Troubleshooting Data Pipeline Performance

    Implementing observability requires having a reliable and high-performance pipeline for telemetry data. However, organizations using open-source platforms often have trouble monitoring and troubleshooting the performance of their data pipeline. This can impair observability as telemetry data is of lower quality.

    Data engineer Abraham Alcantara suggests ten key steps to troubleshoot data pipelines successfully. These include identifying data pipeline software and infrastructure, reproducing and isolating issues and automating issue scenarios. Another strategy is to apply machine learning, such as Coralogix uses.

  • How to use Argo CD to Configure Kubernetes Monitoring in Grafana Cloud

    How to use Argo CD to Configure Kubernetes Monitoring in Grafana Cloud

    Since Kubernetes Monitoring launched in Grafana Cloud last year, we have introduced highly customizable dashboards and powerful analytics features. We’ve also focused on how to make monitoring and managing resource utilization within your fleet easier and more efficient.

    But what’s an easy way to add resources to your cluster while using Kubernetes Monitoring? ArgoCD has become the established tool for implementing GitOps workflows, simplifying the process of deploying and managing Kubernetes resources. If you are using Argo CD to manage your Kubernetes deployments, you can easily configure Grafana Cloud’s Kubernetes Monitoring solution to work with your cluster.

    In this blog post, we’ll walk you through how to use Argo CD to configure Kubernetes Monitoring in Grafana Cloud.

    What is Argo CD?

    Argo CD is a declarative, open source GitOps continuous delivery tool that helps to automate the deployment of applications to Kubernetes clusters. It provides a centralized and standardized way of managing Kubernetes resources in large and complex environments. By using Argo CD, users can easily manage their Kubernetes resources and applications using Git repositories, allowing for version control and auditability.

    Argo CD’s key features and capabilities include the ability to manually or automatically deploy applications to a Kubernetes cluster; automatic synchronization of application state to the current version of declarative configuration; a web user interface and command-line interface; and the ability to detect and remediate configuration drift. It also has role-based access control (RBAC), which allows for multi-cluster management, single sign-on (SSO) with various providers, and support for webhooks that trigger actions.

    Why pair Argo CD with Kubernetes Monitoring in Grafana Cloud?

    Kubernetes Monitoring in Grafana Cloud simplifies monitoring your Kubernetes fleet by:

    • Deploying Grafana Agent with useful defaults for collecting metrics that aid in cardinality management.
    • Providing custom queries to collect useful logs.
    • Offering preconfigured dashboards, alert rules, and recording rules for users to plug into their existing infrastructure.

    But there is some manual effort required to deploy the necessary resources for Kubernetes Monitoring in Grafana Cloud. Users have to copy the configurations and run the commands, which are outlined in Grafana Cloud. While easy enough to do, this process can quickly become error-prone, especially in larger, more complex environments where multiple teams may be deploying resources across multiple clusters. Plus each change must be verified and deployed to each cluster by hand.

    As a result, GitOps tools like Argo CD can help to automate Kubernetes resource deployment. Argo CD takes a declarative, GitOps approach to Kubernetes resource management, allowing for automated and standardized deployments across multiple clusters. This method not only saves time, but also reduces the risk of deployment errors and inconsistencies.

    There are three key advantages to deploying Kubernetes Monitoring with Argo CD:

    1. You’ll use a GitOps-based approach to manage resources required by Grafana Cloud’s Kubernetes Monitoring solution.
    2. It’s easier to make changes in a controlled environment to Grafana Agent configuration and resources.
    3. The Git repository would be maintained as a single source of truth for your Kubernetes resources.
    Architecture diagram of Argo CD set up with Grafana Cloud using arrows and logos.

    Prerequisites for configuring Argo CD with Grafana Cloud

    Before you begin, make sure you have the following available:

    • Argo CD installed and running in your Kubernetes cluster
    • A Git repository to store configuration files
    • A Grafana Cloud account (You can sign up for free today!)

    Metrics and events: Deploy Grafana Agent ConfigMap and StatefulSet

    Create Grafana Agent ConfigMap

    Note: The default scrape interval is set to 60s. Scrape intervals lower than 60s may result in increased costs (DPM > 1). To learn more, see our documentation on active series and DPM.

    Replace
    ${NAMESPACE} with your namespace
    ${METRICS_USERNAME} with Prometheus Instance ID
    ${PROMETHEUS_URL} with the push endpoint URL of the Prometheus Instance
    ${LOGS_USERNAME} with Loki Username ${LOKI_URL} with the push endpoint URL of the Loki Instance
    ${GRAFANA_CLOUD_API_KEY}  with your Grafana Cloud API Key

    Paste the following script into your shell and run it to create the metrics Agent ConfigMap configuration file.

    cat >> metrics.yaml <<'EOF'
    apiVersion: v1
    kind: ConfigMap
    metadata:
     name: grafana-agent
     namespace: ${NAMESPACE}
    data:
     agent.yaml: |   
       metrics:
         wal_directory: /var/lib/agent/wal
         global:
           scrape_interval: 60s
           external_labels:
             cluster: cloud
         configs:
         - name: integrations
           remote_write:
           - url: ${PROMETHEUS_URL}
             basic_auth:
               username:${METRICS_USERNAME}
               password:${GRAFANA_CLOUD_API_KEY}
           scrape_configs:
           - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
             job_name: integrations/kubernetes/cadvisor
             kubernetes_sd_configs:
                 - role: node
             metric_relabel_configs:
                 - source_labels: [__name__]
                   regex: container_fs_writes_bytes_total|container_memory_working_set_bytes|kube_statefulset_metadata_generation|kubelet_pod_worker_duration_seconds_bucket|container_memory_rss|kube_pod_owner|cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests|container_cpu_cfs_periods_total|kubelet_pleg_relist_interval_seconds_bucket|kube_statefulset_status_update_revision|container_fs_writes_total|kube_pod_container_resource_requests|kube_deployment_metadata_generation|kubelet_certificate_manager_server_ttl_seconds|kube_node_status_allocatable|kubelet_running_pod_count|volume_manager_total_volumes|kube_pod_container_resource_limits|kube_persistentvolumeclaim_resource_requests_storage_bytes|rest_client_requests_total|kubelet_volume_stats_inodes_used|kube_job_status_start_time|node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate|container_memory_cache|node_namespace_pod_container:container_memory_swap|container_fs_reads_bytes_total|kube_horizontalpodautoscaler_status_current_replicas|kubelet_pod_start_duration_seconds_count|cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits|namespace_workload_pod|kubelet_running_containers|kubernetes_build_info|kube_node_status_condition|node_namespace_pod_container:container_memory_cache|kubelet_cgroup_manager_duration_seconds_bucket|kube_pod_status_phase|container_network_transmit_packets_dropped_total|kubelet_runtime_operations_errors_total|kube_statefulset_status_current_revision|container_memory_swap|kubelet_volume_stats_capacity_bytes|process_cpu_seconds_total|kube_daemonset_status_desired_number_scheduled|kube_deployment_status_replicas_available|machine_memory_bytes|kube_node_info|kubelet_running_pods|kubelet_server_expiration_renew_errors|container_cpu_usage_seconds_total|namespace_workload_pod:kube_pod_owner:relabel|container_network_transmit_packets_total|go_goroutines|kube_pod_container_status_waiting_reason|kube_horizontalpodautoscaler_spec_min_replicas|kube_job_failed|kube_horizontalpodautoscaler_spec_max_replicas|kube_daemonset_status_current_number_scheduled|namespace_memory:kube_pod_container_resource_requests:sum|kubelet_node_name|kube_statefulset_replicas|namespace_cpu:kube_pod_container_resource_limits:sum|cluster:namespace:pod_memory:active:kube_pod_container_resource_requests|kube_statefulset_status_observed_generation|container_network_transmit_bytes_total|kubelet_volume_stats_available_bytes|kubelet_certificate_manager_client_ttl_seconds|kubelet_runtime_operations_total|node_namespace_pod_container:container_memory_rss|kubelet_pleg_relist_duration_seconds_bucket|storage_operation_errors_total|kubelet_certificate_manager_client_expiration_renew_errors|kube_pod_info|process_resident_memory_bytes|kubelet_pleg_relist_duration_seconds_count|kube_daemonset_status_number_misscheduled|container_network_receive_packets_dropped_total|node_filesystem_size_bytes|kube_statefulset_status_replicas_ready|kube_deployment_status_replicas_updated|kube_deployment_status_observed_generation|kube_deployment_spec_replicas|kube_statefulset_status_replicas_updated|node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile|kube_namespace_status_phase|node_namespace_pod_container:container_memory_working_set_bytes|kubelet_pod_start_duration_seconds_bucket|cluster:namespace:pod_memory:active:kube_pod_container_resource_limits|kubelet_volume_stats_inodes|kube_daemonset_status_updated_number_scheduled|kube_replicaset_owner|container_network_receive_bytes_total|namespace_cpu:kube_pod_container_resource_requests:sum|container_fs_reads_total|kube_node_status_capacity|kube_node_spec_taint|storage_operation_duration_seconds_count|kubelet_pod_worker_duration_seconds_count|kube_resourcequota|node_filesystem_avail_bytes|kubelet_cgroup_manager_duration_seconds_count|kube_horizontalpodautoscaler_status_desired_replicas|namespace_memory:kube_pod_container_resource_limits:sum|container_cpu_cfs_throttled_periods_total|kubelet_node_config_error|kube_job_status_active|kube_daemonset_status_number_available|kube_statefulset_status_replicas|container_network_receive_packets_total|kube_pod_status_reason|kubelet_running_container_count|kube_namespace_status_phase|container_cpu_usage_seconds_total|kube_pod_status_phase|kube_pod_start_time|kube_pod_container_status_restarts_total|kube_pod_container_info|kube_pod_container_status_waiting_reason|kube_daemonset.*|kube_replicaset.*|kube_statefulset.*|kube_job.*|kube_node.*|node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate|cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests|namespace_cpu:kube_pod_container_resource_requests:sum|node_cpu.*|node_memory.*|node_filesystem.*
                   action: keep
             relabel_configs:
                 - replacement: kubernetes.default.svc.cluster.local:443
                   target_label: __address__
                 - regex: (.+)
                   replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
                   source_labels:
                     - __meta_kubernetes_node_name
                   target_label: __metrics_path__
             scheme: https
             tls_config:
                 ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
                 insecure_skip_verify: false
                 server_name: kubernetes
           - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
             job_name: integrations/kubernetes/kubelet
             kubernetes_sd_configs:
                 - role: node
             metric_relabel_configs:
                 - source_labels: [__name__]
                   regex: container_fs_writes_bytes_total|container_memory_working_set_bytes|kube_statefulset_metadata_generation|kubelet_pod_worker_duration_seconds_bucket|container_memory_rss|kube_pod_owner|cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests|container_cpu_cfs_periods_total|kubelet_pleg_relist_interval_seconds_bucket|kube_statefulset_status_update_revision|container_fs_writes_total|kube_pod_container_resource_requests|kube_deployment_metadata_generation|kubelet_certificate_manager_server_ttl_seconds|kube_node_status_allocatable|kubelet_running_pod_count|volume_manager_total_volumes|kube_pod_container_resource_limits|kube_persistentvolumeclaim_resource_requests_storage_bytes|rest_client_requests_total|kubelet_volume_stats_inodes_used|kube_job_status_start_time|node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate|container_memory_cache|node_namespace_pod_container:container_memory_swap|container_fs_reads_bytes_total|kube_horizontalpodautoscaler_status_current_replicas|kubelet_pod_start_duration_seconds_count|cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits|namespace_workload_pod|kubelet_running_containers|kubernetes_build_info|kube_node_status_condition|node_namespace_pod_container:container_memory_cache|kubelet_cgroup_manager_duration_seconds_bucket|kube_pod_status_phase|container_network_transmit_packets_dropped_total|kubelet_runtime_operations_errors_total|kube_statefulset_status_current_revision|container_memory_swap|kubelet_volume_stats_capacity_bytes|process_cpu_seconds_total|kube_daemonset_status_desired_number_scheduled|kube_deployment_status_replicas_available|machine_memory_bytes|kube_node_info|kubelet_running_pods|kubelet_server_expiration_renew_errors|container_cpu_usage_seconds_total|namespace_workload_pod:kube_pod_owner:relabel|container_network_transmit_packets_total|go_goroutines|kube_pod_container_status_waiting_reason|kube_horizontalpodautoscaler_spec_min_replicas|kube_job_failed|kube_horizontalpodautoscaler_spec_max_replicas|kube_daemonset_status_current_number_scheduled|namespace_memory:kube_pod_container_resource_requests:sum|kubelet_node_name|kube_statefulset_replicas|namespace_cpu:kube_pod_container_resource_limits:sum|cluster:namespace:pod_memory:active:kube_pod_container_resource_requests|kube_statefulset_status_observed_generation|container_network_transmit_bytes_total|kubelet_volume_stats_available_bytes|kubelet_certificate_manager_client_ttl_seconds|kubelet_runtime_operations_total|node_namespace_pod_container:container_memory_rss|kubelet_pleg_relist_duration_seconds_bucket|storage_operation_errors_total|kubelet_certificate_manager_client_expiration_renew_errors|kube_pod_info|process_resident_memory_bytes|kubelet_pleg_relist_duration_seconds_count|kube_daemonset_status_number_misscheduled|container_network_receive_packets_dropped_total|node_filesystem_size_bytes|kube_statefulset_status_replicas_ready|kube_deployment_status_replicas_updated|kube_deployment_status_observed_generation|kube_deployment_spec_replicas|kube_statefulset_status_replicas_updated|node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile|kube_namespace_status_phase|node_namespace_pod_container:container_memory_working_set_bytes|kubelet_pod_start_duration_seconds_bucket|cluster:namespace:pod_memory:active:kube_pod_container_resource_limits|kubelet_volume_stats_inodes|kube_daemonset_status_updated_number_scheduled|kube_replicaset_owner|container_network_receive_bytes_total|namespace_cpu:kube_pod_container_resource_requests:sum|container_fs_reads_total|kube_node_status_capacity|kube_node_spec_taint|storage_operation_duration_seconds_count|kubelet_pod_worker_duration_seconds_count|kube_resourcequota|node_filesystem_avail_bytes|kubelet_cgroup_manager_duration_seconds_count|kube_horizontalpodautoscaler_status_desired_replicas|namespace_memory:kube_pod_container_resource_limits:sum|container_cpu_cfs_throttled_periods_total|kubelet_node_config_error|kube_job_status_active|kube_daemonset_status_number_available|kube_statefulset_status_replicas|container_network_receive_packets_total|kube_pod_status_reason|kubelet_running_container_count|kube_namespace_status_phase|container_cpu_usage_seconds_total|kube_pod_status_phase|kube_pod_start_time|kube_pod_container_status_restarts_total|kube_pod_container_info|kube_pod_container_status_waiting_reason|kube_daemonset.*|kube_replicaset.*|kube_statefulset.*|kube_job.*|kube_node.*|node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate|cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests|namespace_cpu:kube_pod_container_resource_requests:sum|node_cpu.*|node_memory.*|node_filesystem.*
                   action: keep
             relabel_configs:
                 - replacement: kubernetes.default.svc.cluster.local:443
                   target_label: __address__
                 - regex: (.+)
                   replacement: /api/v1/nodes/${1}/proxy/metrics
                   source_labels:
                     - __meta_kubernetes_node_name
                   target_label: __metrics_path__
             scheme: https
             tls_config:
                 ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
                 insecure_skip_verify: false
                 server_name: kubernetes
           - job_name: integrations/kubernetes/kube-state-metrics
             kubernetes_sd_configs:
                 - role: pod
             metric_relabel_configs:
                 - source_labels: [__name__]
                   regex: container_fs_writes_bytes_total|container_memory_working_set_bytes|kube_statefulset_metadata_generation|kubelet_pod_worker_duration_seconds_bucket|container_memory_rss|kube_pod_owner|cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests|container_cpu_cfs_periods_total|kubelet_pleg_relist_interval_seconds_bucket|kube_statefulset_status_update_revision|container_fs_writes_total|kube_pod_container_resource_requests|kube_deployment_metadata_generation|kubelet_certificate_manager_server_ttl_seconds|kube_node_status_allocatable|kubelet_running_pod_count|volume_manager_total_volumes|kube_pod_container_resource_limits|kube_persistentvolumeclaim_resource_requests_storage_bytes|rest_client_requests_total|kubelet_volume_stats_inodes_used|kube_job_status_start_time|node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate|container_memory_cache|node_namespace_pod_container:container_memory_swap|container_fs_reads_bytes_total|kube_horizontalpodautoscaler_status_current_replicas|kubelet_pod_start_duration_seconds_count|cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits|namespace_workload_pod|kubelet_running_containers|kubernetes_build_info|kube_node_status_condition|node_namespace_pod_container:container_memory_cache|kubelet_cgroup_manager_duration_seconds_bucket|kube_pod_status_phase|container_network_transmit_packets_dropped_total|kubelet_runtime_operations_errors_total|kube_statefulset_status_current_revision|container_memory_swap|kubelet_volume_stats_capacity_bytes|process_cpu_seconds_total|kube_daemonset_status_desired_number_scheduled|kube_deployment_status_replicas_available|machine_memory_bytes|kube_node_info|kubelet_running_pods|kubelet_server_expiration_renew_errors|container_cpu_usage_seconds_total|namespace_workload_pod:kube_pod_owner:relabel|container_network_transmit_packets_total|go_goroutines|kube_pod_container_status_waiting_reason|kube_horizontalpodautoscaler_spec_min_replicas|kube_job_failed|kube_horizontalpodautoscaler_spec_max_replicas|kube_daemonset_status_current_number_scheduled|namespace_memory:kube_pod_container_resource_requests:sum|kubelet_node_name|kube_statefulset_replicas|namespace_cpu:kube_pod_container_resource_limits:sum|cluster:namespace:pod_memory:active:kube_pod_container_resource_requests|kube_statefulset_status_observed_generation|container_network_transmit_bytes_total|kubelet_volume_stats_available_bytes|kubelet_certificate_manager_client_ttl_seconds|kubelet_runtime_operations_total|node_namespace_pod_container:container_memory_rss|kubelet_pleg_relist_duration_seconds_bucket|storage_operation_errors_total|kubelet_certificate_manager_client_expiration_renew_errors|kube_pod_info|process_resident_memory_bytes|kubelet_pleg_relist_duration_seconds_count|kube_daemonset_status_number_misscheduled|container_network_receive_packets_dropped_total|node_filesystem_size_bytes|kube_statefulset_status_replicas_ready|kube_deployment_status_replicas_updated|kube_deployment_status_observed_generation|kube_deployment_spec_replicas|kube_statefulset_status_replicas_updated|node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile|kube_namespace_status_phase|node_namespace_pod_container:container_memory_working_set_bytes|kubelet_pod_start_duration_seconds_bucket|cluster:namespace:pod_memory:active:kube_pod_container_resource_limits|kubelet_volume_stats_inodes|kube_daemonset_status_updated_number_scheduled|kube_replicaset_owner|container_network_receive_bytes_total|namespace_cpu:kube_pod_container_resource_requests:sum|container_fs_reads_total|kube_node_status_capacity|kube_node_spec_taint|storage_operation_duration_seconds_count|kubelet_pod_worker_duration_seconds_count|kube_resourcequota|node_filesystem_avail_bytes|kubelet_cgroup_manager_duration_seconds_count|kube_horizontalpodautoscaler_status_desired_replicas|namespace_memory:kube_pod_container_resource_limits:sum|container_cpu_cfs_throttled_periods_total|kubelet_node_config_error|kube_job_status_active|kube_daemonset_status_number_available|kube_statefulset_status_replicas|container_network_receive_packets_total|kube_pod_status_reason|kubelet_running_container_count|kube_namespace_status_phase|container_cpu_usage_seconds_total|kube_pod_status_phase|kube_pod_start_time|kube_pod_container_status_restarts_total|kube_pod_container_info|kube_pod_container_status_waiting_reason|kube_daemonset.*|kube_replicaset.*|kube_statefulset.*|kube_job.*|kube_node.*|node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate|cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests|namespace_cpu:kube_pod_container_resource_requests:sum|node_cpu.*|node_memory.*|node_filesystem.*
                   action: keep
             relabel_configs:
                 - action: keep
                   regex: kube-state-metrics
                   source_labels:
                     - __meta_kubernetes_pod_label_app_kubernetes_io_name
           - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
             job_name: integrations/node_exporter
             kubernetes_sd_configs:
                 - namespaces:
                     names:
                         - default
                   role: pod
             metric_relabel_configs:
                 - source_labels: [__name__]
                   regex: container_fs_writes_bytes_total|container_memory_working_set_bytes|kube_statefulset_metadata_generation|kubelet_pod_worker_duration_seconds_bucket|container_memory_rss|kube_pod_owner|cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests|container_cpu_cfs_periods_total|kubelet_pleg_relist_interval_seconds_bucket|kube_statefulset_status_update_revision|container_fs_writes_total|kube_pod_container_resource_requests|kube_deployment_metadata_generation|kubelet_certificate_manager_server_ttl_seconds|kube_node_status_allocatable|kubelet_running_pod_count|volume_manager_total_volumes|kube_pod_container_resource_limits|kube_persistentvolumeclaim_resource_requests_storage_bytes|rest_client_requests_total|kubelet_volume_stats_inodes_used|kube_job_status_start_time|node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate|container_memory_cache|node_namespace_pod_container:container_memory_swap|container_fs_reads_bytes_total|kube_horizontalpodautoscaler_status_current_replicas|kubelet_pod_start_duration_seconds_count|cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits|namespace_workload_pod|kubelet_running_containers|kubernetes_build_info|kube_node_status_condition|node_namespace_pod_container:container_memory_cache|kubelet_cgroup_manager_duration_seconds_bucket|kube_pod_status_phase|container_network_transmit_packets_dropped_total|kubelet_runtime_operations_errors_total|kube_statefulset_status_current_revision|container_memory_swap|kubelet_volume_stats_capacity_bytes|process_cpu_seconds_total|kube_daemonset_status_desired_number_scheduled|kube_deployment_status_replicas_available|machine_memory_bytes|kube_node_info|kubelet_running_pods|kubelet_server_expiration_renew_errors|container_cpu_usage_seconds_total|namespace_workload_pod:kube_pod_owner:relabel|container_network_transmit_packets_total|go_goroutines|kube_pod_container_status_waiting_reason|kube_horizontalpodautoscaler_spec_min_replicas|kube_job_failed|kube_horizontalpodautoscaler_spec_max_replicas|kube_daemonset_status_current_number_scheduled|namespace_memory:kube_pod_container_resource_requests:sum|kubelet_node_name|kube_statefulset_replicas|namespace_cpu:kube_pod_container_resource_limits:sum|cluster:namespace:pod_memory:active:kube_pod_container_resource_requests|kube_statefulset_status_observed_generation|container_network_transmit_bytes_total|kubelet_volume_stats_available_bytes|kubelet_certificate_manager_client_ttl_seconds|kubelet_runtime_operations_total|node_namespace_pod_container:container_memory_rss|kubelet_pleg_relist_duration_seconds_bucket|storage_operation_errors_total|kubelet_certificate_manager_client_expiration_renew_errors|kube_pod_info|process_resident_memory_bytes|kubelet_pleg_relist_duration_seconds_count|kube_daemonset_status_number_misscheduled|container_network_receive_packets_dropped_total|node_filesystem_size_bytes|kube_statefulset_status_replicas_ready|kube_deployment_status_replicas_updated|kube_deployment_status_observed_generation|kube_deployment_spec_replicas|kube_statefulset_status_replicas_updated|node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile|kube_namespace_status_phase|node_namespace_pod_container:container_memory_working_set_bytes|kubelet_pod_start_duration_seconds_bucket|cluster:namespace:pod_memory:active:kube_pod_container_resource_limits|kubelet_volume_stats_inodes|kube_daemonset_status_updated_number_scheduled|kube_replicaset_owner|container_network_receive_bytes_total|namespace_cpu:kube_pod_container_resource_requests:sum|container_fs_reads_total|kube_node_status_capacity|kube_node_spec_taint|storage_operation_duration_seconds_count|kubelet_pod_worker_duration_seconds_count|kube_resourcequota|node_filesystem_avail_bytes|kubelet_cgroup_manager_duration_seconds_count|kube_horizontalpodautoscaler_status_desired_replicas|namespace_memory:kube_pod_container_resource_limits:sum|container_cpu_cfs_throttled_periods_total|kubelet_node_config_error|kube_job_status_active|kube_daemonset_status_number_available|kube_statefulset_status_replicas|container_network_receive_packets_total|kube_pod_status_reason|kubelet_running_container_count|kube_namespace_status_phase|container_cpu_usage_seconds_total|kube_pod_status_phase|kube_pod_start_time|kube_pod_container_status_restarts_total|kube_pod_container_info|kube_pod_container_status_waiting_reason|kube_daemonset.*|kube_replicaset.*|kube_statefulset.*|kube_job.*|kube_node.*|node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate|cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests|namespace_cpu:kube_pod_container_resource_requests:sum|node_cpu.*|node_memory.*|node_filesystem.*
                   action: keep
             relabel_configs:
                 - action: keep
                   regex: prometheus-node-exporter.*
                   source_labels:
                     - __meta_kubernetes_pod_label_app_kubernetes_io_name
                 - action: replace
                   source_labels:
                     - __meta_kubernetes_pod_node_name
                   target_label: instance
                 - action: replace
                   source_labels:
                     - __meta_kubernetes_namespace
                   target_label: namespace
             tls_config:
                 ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
                 insecure_skip_verify: false
          
       integrations:
         eventhandler:
           cache_path: /var/lib/agent/eventhandler.cache
           logs_instance: integrations
       logs:
         configs:
         - name: integrations
           clients:
           - url: ${GRAFANA_CLOUD_API_KEY}
             basic_auth:
               username: ${LOGS_USERNAME}
               password: ${LOKI_URL}
             external_labels:
               cluster: cloud
               job: integrations/kubernetes/eventhandler
           positions:
             filename: /tmp/positions.yaml
           target_config:
             sync_period: 10s
    

    This ConfigMap configures the Grafana Agent StatefulSet to scrape the cadvisor, kubelet, and kube-state-metrics endpoints in your cluster. It also configures Grafana Agent to collect Kubernetes events from your cluster’s control plane and ship these to your Grafana Cloud Loki instance. To learn more about configuring Grafana Agent, see our  Grafana Agent configuration reference docs.

    Create Grafana Agent StatefulSet

    Replace ${NAMESPACE} with your namespace and paste the following script into your shell and run it to create the configuration file for metrics Grafana Agent StatefulSet.

    cat >> metrics-agent.yaml <<'EOF'
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: grafana-agent
     namespace: ${NAMESPACE}
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
     name: grafana-agent
    rules:
    - apiGroups:
     - ""
     resources:
     - nodes
     - nodes/proxy
     - services
     - endpoints
     - pods
     - events
     verbs:
     - get
     - list
     - watch
    - nonResourceURLs:
     - /metrics
     verbs:
     - get
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
     name: grafana-agent
    roleRef:
     apiGroup: rbac.authorization.k8s.io
     kind: ClusterRole
     name: grafana-agent
    subjects:
    - kind: ServiceAccount
     name: grafana-agent
     namespace: ${NAMESPACE}
    ---
    apiVersion: v1
    kind: Service
    metadata:
     labels:
       name: grafana-agent
     name: grafana-agent
     namespace: ${NAMESPACE}
    spec:
     clusterIP: None
     ports:
     - name: grafana-agent-http-metrics
       port: 80
       targetPort: 80
     selector:
       name: grafana-agent
    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
     name: grafana-agent
     namespace: ${NAMESPACE}
    spec:
     replicas: 1
     selector:
       matchLabels:
         name: grafana-agent
     serviceName: grafana-agent
     template:
       metadata:
         labels:
           name: grafana-agent
       spec:
         containers:
         - args:
           - -config.expand-env=true
           - -config.file=/etc/agent/agent.yaml
           - -enable-features=integrations-next
           - -server.http.address=0.0.0.0:80
           env:
           - name: HOSTNAME
             valueFrom:
               fieldRef:
                 fieldPath: spec.nodeName
           image: grafana/agent:v0.32.1
           imagePullPolicy: IfNotPresent
           name: grafana-agent
           ports:
           - containerPort: 80
             name: http-metrics
           volumeMounts:
           - mountPath: /var/lib/agent
             name: agent-wal
           - mountPath: /etc/agent
             name: grafana-agent
         serviceAccountName: grafana-agent
         volumes:
         - configMap:
             name: grafana-agent
           name: grafana-agent
     updateStrategy:
       type: RollingUpdate
     volumeClaimTemplates:
     - apiVersion: v1
       kind: PersistentVolumeClaim
       metadata:
         name: agent-wal
         namespace: ${NAMESPACE}
       spec:
         accessModes:
         - ReadWriteOnce
         resources:
           requests:
             storage: 5Gi
    

    Kube-state-metrics

    kube-state-metrics watches Kubernetes resources in your cluster and emits Prometheus metrics that can be scraped by Grafana Agent. To learn more, see the kube-state-metrics docs.

    Replace ${Argo CD_NAMESPACE} with your namespace in which Argo CD is deployed and ${NAMESPACE} with the namespace where you want to deploy Kubernetes Monitoring resources. Then paste the following script into your shell and run it to create the configuration file for kube-state-metrics Argo CD application.

    Node_exporter

    Node_exporter is used to collect host metrics from each node in your cluster, and emits them as Prometheus metrics.

    Replace ${Argo CD_NAMESPACE} with your namespace in which Argo CD is deployed and ${NAMESPACE} with the namespace where you want to deploy Kubernetes Monitoring resources. Then paste the following script into your shell and run it to create the configuration file for node_exporter Argo CD application.

    cat >> node-exporter.yaml <<'EOF'
    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
     name: nodeexporter
     namespace: ${Argo CD_NAMESPACE}
    spec:
     destination:
       name: ''
       namespace: ${NAMESPACE}
       server: 'https://kubernetes.default.svc'
     source:
       path: ''
       repoURL: 'https://prometheus-community.github.io/helm-charts'
       targetRevision: 4.16.0
       chart: prometheus-node-exporter
     sources: []
     project: default
     syncPolicy:
       automated:
         prune: true
         selfHeal: true
       retry:
         limit: 2
         backoff:
           duration: 5s
           maxDuration: 3m0s
           factor: 2
       syncOptions:
         - CreateNamespace=true
    

    Logs: Deploy Grafana Agent ConfigMap and DaemonSet

    Create Grafana Agent ConfigMap

    Replace
    ${NAMESPACE} with your namespace
    ${METRICS_USERNAME} with Prometheus Instance ID
    ${PROMETHEUS_URL} with the push endpoint URL of the Prometheus Instance
    ${LOGS_USERNAME} with Loki Username
    ${LOKI_URL} with the push endpoint URL of the Loki Instance
    ${GRAFANA_CLOUD_API_KEY}

    Paste the following script into your shell and run it to create the logs Agent ConfigMap configuration file.

    cat >> logs.yaml <<'EOF'
    apiVersion: v1
    kind: ConfigMap
    metadata:
     name: grafana-agent-logs
     namespace: ${NAMESPACE}
    data:
     agent.yaml: |   
       metrics:
         wal_directory: /tmp/grafana-agent-wal
         global:
           scrape_interval: 60s
           external_labels:
             cluster: cloud
         configs:
         - name: integrations
           remote_write:
           - url: ${PROMETHEUS_URL}
             basic_auth:
               username: ${METRICS_USERNAME}
               password: ${GRAFANA_CLOUD_API_KEY}
       integrations:
         prometheus_remote_write:
         - url: ${PROMETHEUS_URL}
           basic_auth:
             username: ${METRICS_USERNAME}
             password: ${GRAFANA_CLOUD_API_KEY}
        
        
       logs:
         configs:
         - name: integrations
           clients:
           - url: ${LOKI_URL}
             basic_auth:
               username: ${LOGS_USERNAME}
               password: ${GRAFANA_CLOUD_API_KEY}
             external_labels:
               cluster: cloud
           positions:
             filename: /tmp/positions.yaml
           target_config:
             sync_period: 10s
           scrape_configs:
           - job_name: integrations/kubernetes/pod-logs
             kubernetes_sd_configs:
               - role: pod
             pipeline_stages:
               - docker: {}
             relabel_configs:
               - source_labels:
                   - __meta_kubernetes_pod_node_name
                 target_label: __host__
               - action: replace
                 replacement: $1
                 separator: /
                 source_labels:
                   - __meta_kubernetes_namespace
                   - __meta_kubernetes_pod_name
                 target_label: job
               - action: replace
                 source_labels:
                   - __meta_kubernetes_namespace
                 target_label: namespace
               - action: replace
                 source_labels:
                   - __meta_kubernetes_pod_name
                 target_label: pod
               - action: replace
                 source_labels:
                   - __meta_kubernetes_pod_container_name
                 target_label: container
               - replacement: /var/log/pods/*$1/*.log
                 separator: /
                 source_labels:
                   - __meta_kubernetes_pod_uid
                   - __meta_kubernetes_pod_container_name
                 target_label: __path__
    

    Create Grafana Agent DaemonSet

    Replace ${NAMESPACE} with your namespace and paste the following script into your shell and run it to create the configuration file for Logs Grafana Agent DaemonSet.

    cat >> logs-agent.yaml <<'EOF'
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: grafana-agent-logs
     namespace: ${NAMESPACE}
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
     name: grafana-agent-logs
    rules:
    - apiGroups:
     - ""
     resources:
     - nodes
     - nodes/proxy
     - services
     - endpoints
     - pods
     - events
     verbs:
     - get
     - list
     - watch
    - nonResourceURLs:
     - /metrics
     verbs:
     - get
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
     name: grafana-agent-logs
    roleRef:
     apiGroup: rbac.authorization.k8s.io
     kind: ClusterRole
     name: grafana-agent-logs
    subjects:
    - kind: ServiceAccount
     name: grafana-agent-logs
     namespace: default
    ---
    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
     name: grafana-agent-logs
     namespace: ${NAMESPACE}
    spec:
     minReadySeconds: 10
     selector:
       matchLabels:
         name: grafana-agent-logs
     template:
       metadata:
         labels:
           name: grafana-agent-logs
       spec:
         containers:
         - args:
           - -config.expand-env=true
           - -config.file=/etc/agent/agent.yaml
           - -server.http.address=0.0.0.0:80
           env:
           - name: HOSTNAME
             valueFrom:
               fieldRef:
                 fieldPath: spec.nodeName
           image: grafana/agent:v0.32.1
           imagePullPolicy: IfNotPresent
           name: grafana-agent-logs
           ports:
           - containerPort: 80
             name: http-metrics
           securityContext:
             privileged: true
             runAsUser: 0
           volumeMounts:
           - mountPath: /etc/agent
             name: grafana-agent-logs
           - mountPath: /var/log
             name: varlog
           - mountPath: /var/lib/docker/containers
             name: varlibdockercontainers
             readOnly: true
         serviceAccountName: grafana-agent-logs
         tolerations:
         - effect: NoSchedule
           operator: Exists
         volumes:
         - configMap:
             name: grafana-agent-logs
           name: grafana-agent-logs
         - hostPath:
             path: /var/log
           name: varlog
         - hostPath:
             path: /var/lib/docker/containers
           name: varlibdockercontainers
     updateStrategy:
       type: RollingUpdate
    

    Git repository setup

    The ideal setup is to have changes that are made to the main branch of your Git repository automatically synced within Kubernetes. To achieve this, follow the steps below:

    1. Create a folder in your Git repository (For this post, let’s create a folder named kubernetes-monitoring).
    2. Push all the manifest files for earlier steps (metrics.yaml, metrics-agent.yaml, kube-state-metrics.yaml, node-exporter.yaml, logs.yaml and logs-agent.yaml) into the newly created folder.

    Argo CD application setup

    Screenshot of Argo CD web interface for creating a new app.
    ArgoCD New App web interface.

    In the Argo CD web interface, click on the New App button. Enter a name for the application, such as grafana-kubernetes-monitoring, and select the your desired project name (if there is none, select default) and sync policy as automatic. Select Prune Resources and Self Heal options to ensure configuration in Git Repository is always maintained within the Kubernetes cluster. Also tick the Auto-Create Namespace option and the Retry options.

    Under Source, enter the URL for your Git repository along with the revision (by default it is HEAD). Set the path to the folder (kubernetes-monitoring).

    Under Destination, enter your cluster URL. If it’s the same cluster where Argo CD is deployed, use https://kubernetes.default.svc and the namespace for creating the application resource. The namespace should be the same as the one where Argo CD is deployed.

    Select Directory Recurse as its useful when having configuration files within nested folders

    Finally, click on the Create button to create the application.

    You can also run the below command to create the Argo CD application that monitors your Git Repository folder for changes. Make sure to replace ${GIT_REPO_URL} with your Git Repository URL; ${Argo CD_NAMESPACE} with your namespace in which Argo CD is deployed; and ${NAMESPACE} with the namespace where you want to deploy Kubernetes Monitoring resources.

    cat <<'EOF' | kubectl apply -f -
    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
     name: kubernetes-monitoring
     namespace: ${Argo CD_NAMESPACE}
    spec:
     destination:
       name: ''
       namespace: ${NAMESPACE}
       server: 'https://kubernetes.default.svc'
     source:
       path: kubernetes-monitoring
       repoURL: '${GIT_REPO_URL}'
       targetRevision: HEAD
       directory:
         recurse: true
     sources: []
     project: default
     syncPolicy:
       automated:
         prune: true
         selfHeal: true
       retry:
         limit: 3
         backoff:
           duration: 5s
           maxDuration: 3m0s
           factor: 2
       syncOptions:
         - CreateNamespace=true
    

    Once the application has been created, the Kubernetes manifest defined in the Git repository will be automatically deployed.

    Install prebuilt Grafana dashboards and alerts

    Note: You must have the Admin role to install dashboards and alerts in Grafana Cloud.

    Navigate to your Grafana Cloud instance and in the navigation menu, select Kubernetes under the Monitoring section.

    Go to the configuration and click on Install dashboards and alert rules.

    The configuration has been already completed, so you can now start viewing dashboards.

    Once the metrics and logs from your Kubernetes cluster are being ingested into Grafana Cloud, you can:

    • Easily navigate around your Kubernetes setup using a single UI. Begin with a cluster view and drill down to specific Kubernetes pods with the preconfigured Grafana dashboards.
    • Use node observability. Find out more about node health along with pod density and node logs.
    • Use the cluster efficiency dashboard. Understand your resource usage and use the information for capacity planning and optimizing costs and efficiency.
    • Stay on top of your cluster. Use the preconfigured Grafana alerts to monitor your fleet.

    Next steps for monitoring Kubernetes clusters with Grafana Cloud

    Once you have settled into your new Argo CD configuration, you can continue to expand on your observability strategy with Kubernetes Monitoring in Grafana Cloud.

    You can leverage the latest integrations available within the Kubernetes Monitoring solution such as Cert Manager, CockroachDB and more. To configure scraping application pod metrics, you can refer to our detailed documentation. And while Kubernetes Monitoring currently covers metrics and logs, to get a complete timeline into data transactions, request durations, and bottlenecks, it is also important to use traces. You can configure your applications to send traces to Grafana Agent, which can then be configured to send that tracing data to Grafana Cloud’s hosted tracing instance.

    The easiest way to get started with Kubernetes Monitoring is with Grafana Cloud. We have a generous free forever tier and plans for every use case. Sign up for free today!

  • Five Great DevOps Job Opportunities

    Five Great DevOps Job Opportunities

    devopsy.kinsta.cloud is now providing a weekly DevOps jobs report through which opportunities for DevOps professionals will be highlighted to better serve our audience.

    Our goal in these challenging economic times is to make it easier for DevOps professionals to advance their careers.

    Of course, the pool of available DevOps talent is still relatively constrained, so when one DevOps professional takes on a new role it tends to create an opportunity for others.

    The five job postings shared this week are selected based on the company looking to hire, the vertical industry segment and, naturally, the pay scale being offered.

    We’re also committed to providing additional insights into the state of the DevOps job market. In the meantime, for your consideration:

    LinkedIn

    Harris Allied
    New York, New York
    DevOps Engineer
    $160,000 to $175,000

    CareerBuilder.com

    MassMutual Financial Group
    Remote
    DevOps/Kubernetes Cloud Infrastructure Engineer

    $137,800 to $180,800

    Indeed.com

    Lawrence Livermore Labs
    Livermore, California
    DevOps Engineer
    $123,960 to $159,168

    SimplyHired.com

    CVS Health
    Remote
    DevOps Engineer
    $90,000 to $180,000

    Dice.com

    Idea Entity
    Herndon, Virginia
    Azure DevOps Engineer
    $80,000 to $100,000