{"id":619,"date":"2025-04-07T05:22:02","date_gmt":"2025-04-07T05:22:02","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=619"},"modified":"2025-04-07T05:22:02","modified_gmt":"2025-04-07T05:22:02","slug":"private-eks-resources","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=619","title":{"rendered":"Access Private EKS Resources Using OpenVPN(complete Guide)"},"content":{"rendered":"<p>In this blog, you will learn to securely access private EKS resources with the help of an OpenVPN server.<\/p>\n<h2 id=\"setup-architecture-and-workflow\">Setup Architecture and Workflow<\/h2>\n<p>When it comes to secure EKS implementation, the clusters needs to be in a fully private subnet. <\/p>\n<p>When you deploy applications in a Private EKS cluster, you need a bastion host or a VPN setup to seamlessly access the applications in the cluster.<\/p>\n<p>For example, lets say you deploy Prometheus or Loki stack in the cluster, to access the dashboards, you need to have access to the Internal Load Balancer. <\/p>\n<p>Here is where OpenVPN server comes in to picture. <\/p>\n<p>From our local workstations, the VPN server will create a <strong>secure, encrypted tunnel<\/strong> over the internet to communicate with the private networks in AWS cloud infrastrucure. <\/p>\n<p>We will set up an OpenVPN&nbsp;self-hosted server on an EC2 instance and configure it to communicate with private subnets where the EKS cluster resides. This way, the resources on that private subnets cab be accessed from our local machine.<\/p>\n<p>The following architecture diagram explains the private communication between the client (local workstation) and the AWS resources. <\/p>\n<figure class=\"kg-card kg-image-card kg-card-hascaption\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/04\/OpenVPN-EKS-cluster-access.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1920\" height=\"1080\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/04\/OpenVPN-EKS-cluster-access.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/04\/OpenVPN-EKS-cluster-access.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/04\/OpenVPN-EKS-cluster-access.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/04\/OpenVPN-EKS-cluster-access.png 1920w\" sizes=\"auto, (min-width: 720px) 720px\"><figcaption><span style=\"white-space: pre-wrap;\">l<\/span><\/figcaption><\/figure>\n<p>The above diagram explains, <\/p>\n<ol>\n<li>The OpenVPN community edition will be installed in the <a href=\"https:\/\/devopscube.com\/aws-ssm\/\" rel=\"noreferrer\">EC2 instance <\/a>(Amazon Linux 2) with the public subnet, because the server needs internet access. <\/li>\n<li>After the installation of the VPN Server, we will generate a client configuration file for the connection implementation. <\/li>\n<li>Once the user (Client) gets the configuration file, it will be imported into the OpenVPN Client app to establish the connection to the VPN Server, so the connection will be established.<\/li>\n<li>Through the secure connection implemented, we can connect to the private EKS resources, which are implemented on private subnets.<\/li>\n<\/ol>\n<h2 id=\"overall-setup\">Overall Setup <\/h2>\n<p>We will deploy the <a href=\"https:\/\/devopscube.com\/prometheus-certified-associate\/\" rel=\"noreferrer\">Prometheus<\/a> stack on the private EKS cluster for testing purposes so that we will know how we are able to access its dashboard from our local machine. <\/p>\n<p>But you can install anything, such as a private Nginx server pod, which is also ok for testing. <\/p>\n<p>After the deployment, we will test the connection using the Node Port service as well as the internal load balancer with the help of the <a href=\"https:\/\/devopscube.com\/aws-load-balancer-controller-on-eks\/\" rel=\"noreferrer\">AWS Load Balancer Controller<\/a> and Ingress object.<\/p>\n<h2 id=\"setup-prerequisites\">Setup Prerequisites<\/h2>\n<ol>\n<li>A VPC with Public Subnets (Where OpenVPN gets deployed)<\/li>\n<li>A bastion host\/jump server deployed in the EKS VPC to access to EKS cluster.<\/li>\n<li>A Running Private EKS cluster (&gt;= v1.30)<\/li>\n<li>Helm installed and configured on the local system to deploy apps to EKS.<\/li>\n<\/ol>\n<h2 id=\"set-openvpn-server\">Set OpenVPN Server<\/h2>\n<p>We have covered the OpenVPN server setup in detail in a separate blog.<\/p>\n<p>It covers the following topics,<\/p>\n<ol>\n<li>Setting up OpenVPN on Amazon Linux<\/li>\n<li>OpenVPN server configuration<\/li>\n<li>OpenVPN Client Cert Configuration<\/li>\n<li>Validating VPN Tunnel Configurations.<\/li>\n<\/ol>\n<p><strong>Refer:<\/strong> <a href=\"https:\/\/devopscube.com\/setup-openvpn-server-in-ec2\/\" rel=\"noreferrer\">OpenVPN Server In EC2<\/a><\/p>\n<p>Once you have the VPN server up and running in the public subnet, proceed to the Following.<\/p>\n<h2 id=\"deploy-a-bastion-server-in-eks-vpc\">Deploy a Bastion Server in EKS VPC<\/h2>\n<p>To directly access the private EKS cluster, we need a jump server on the same VPN with internet access. <\/p>\n<p>So, we create an Ubuntu server on the same VPC of the EKS cluster, but the difference is that we use the public subnet instead.<\/p>\n<p>Once the instance is created, you need to add the instance profile (IAM Role) with the required permission to access the cluster, or you can add the IAM user&#8217;s credentials, such as the access key and secret access key for the cluster access.<\/p>\n<p>Ensure that all the necessary tools, such as AWS CLI, Helm, Kubectl, and Eksctl, are bastion servers available in the cluster management. <\/p>\n<p>Once every thing is set, use the following command to, update the kubeconfig to the bastion server.<\/p>\n<pre><code>aws eks update-kubeconfig --name &lt;CLUSTER_NAME&gt; --region &lt;REGION&gt;<\/code><\/pre>\n<blockquote><p>Note: Add a rule in Private EKS cluster&#8217;s security group to enable port <code>443<\/code> to the bastion server for API access.<\/p><\/blockquote>\n<blockquote><p>Note: Add the instance profile or the IAM user, which is using on the bastion server for access should be updated on the EKS clusters access section.<\/p><\/blockquote>\n<p>Now, we can deploy the demo apps on the private EKS cluster for the testing.<\/p>\n<h2 id=\"deploy-prometheus-stack-in-private-eks-cluster\">Deploy Prometheus Stack in Private EKS Cluster<\/h2>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udccc<\/div>\n<div class=\"kg-callout-text\">For demo purposes, to access multiple endpoints, we are using the Prometheus stack with Prometheus, Grafana, and Alertmanager endpoints. You can choose to deploy different apps for testing.<\/div>\n<\/div>\n<p>To achieve this, we need to expose the applications with <strong>Node Port<\/strong> service, so I am creating a new <code>values.yaml<\/code> file to deploy the Prometheus stack with Node Port service.<\/p>\n<p>Create a values file for the Prometheus stack Helm deployment<\/p>\n<pre><code>cat &lt;&lt;EOF &gt; node-port-values.yaml\ngrafana:\n  service:\n    type: NodePort\n    nodePort: 30000\n\nprometheus:\n  service:\n    type: NodePort\n    nodePort: 30001\n\nalertmanager:\n  service:\n    type: NodePort\n    nodePort: 30002\nEOF<\/code><\/pre>\n<p>To add the Prometheus Operator repo, use the following command.<\/p>\n<pre><code>helm repo add prometheus-community https:\/\/prometheus-community.github.io\/helm-charts<\/code><\/pre>\n<p>To install the Prometheus Operator stack with a custom values file, use the following command.<\/p>\n<pre><code>helm install prometheus prometheus-community\/kube-prometheus-stack -n monitoring --create-namespace -f node-port-values.yaml<\/code><\/pre>\n<p>Once the installation is completed, you can see the status of the deployments and the services.<\/p>\n<pre><code>kubectl -n monitoring get po,svc<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-98.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1866\" height=\"758\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-98.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-98.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-98.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-98.png 1866w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\">Note down the <code spellcheck=\"false\" style=\"white-space: pre-wrap;\">NodePort<\/code> number. <\/p>\n<p>We need to enable these Ports on the Private EKS cluster security group to be accessed from OpenVPN server.<\/p><\/div>\n<\/div>\n<p>Navigate to the EKS dashboard and open the <code>Networking<\/code> section and click the cluster security group of the cluster.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-99-2.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1310\" height=\"854\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-99-2.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-99-2.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-99-2.png 1310w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Need to add three inbound rules for <a href=\"https:\/\/devopscube.com\/grafana-loki-architecture\/\" rel=\"noreferrer\">Grafana<\/a> (30000), Prometheus (30001), and Alertmanager (30002) <strong><code>NodePorts<\/code><\/strong>.<\/p>\n<p>As highlighted in the following image, we need to add the port, and in the source, you need to add the <strong>security group ID of the OpenVPN server<\/strong>. This will allow the OpenVPN server to access these ports on the EKS cluster.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-100-2.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1710\" height=\"815\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-100-2.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-100-2.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-100-2.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-100-2.png 1710w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Save the security groups rules. Next step is to validate the connectivity from VPN.<\/p>\n<h2 id=\"validate-vpn-to-cluster-connectivity\">Validate VPN to Cluster Connectivity<\/h2>\n<p>First , ensure the OpenVPN connection is active.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-102-1.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"389\" height=\"374\"><\/figure>\n<p>To test the connection, we need any of the EKS cluster node&#8217;s private IP and the <code>NodePort<\/code> number of the service.<\/p>\n<p>To get the node&#8217;s IP, use the following kubectl command.<\/p>\n<pre><code>kubectl get no -o wide<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-104-1.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1807\" height=\"632\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-104-1.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-104-1.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-104-1.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-104-1.png 1807w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Now, lets try accessing the Prometheus dashboard.<\/p>\n<p>Open any of the web browsers from the local machine and paste the <strong><code>&lt;NODE_IP&gt;:30001<\/code><\/strong><\/p>\n<p>As shown below, you should be able to access the Prometheus dashboard using the Private IP of the EKS node.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-105-2.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1057\" height=\"505\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-105-2.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-105-2.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-105-2.png 1057w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>For Alertmanager Dashboard, access <strong><code>&lt;NODE_IP&gt;:30002<\/code><\/strong><\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-106-1.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1059\" height=\"570\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-106-1.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-106-1.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-106-1.png 1059w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>To access Grafana Dashboard, access <strong><code>&lt;NODE_IP&gt;:30003<\/code><\/strong><\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-107.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1062\" height=\"737\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-107.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-107.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-107.png 1062w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Using the IP method is ok for the testing purposes. <\/p>\n<p>As you might know the EKS nodes are ephemeral. Meaning when a node gets deleted and recreated, the IP will changed. So you cannot rely on worker node IPs.<\/p>\n<p>To avoid this, we need to expose the services with an <strong>Internal Load Balancer.<\/strong> Then with the load balancer IP or DNS name, we can access the applications with the static endpoint without worrying about IP changes.<\/p>\n<h2 id=\"expose-applications-via-an-internal-aws-load-balancer\">Expose Applications via an Internal AWS Load Balancer<\/h2>\n<p>Assuming you will have more than one applications to access, you will need a ingress based setup. Or else you will have to deploy one loadbalancer for each service which gets expensive.<\/p>\n<p>For ingress to work, we need the <strong>AWS load balancer controller.<\/strong> <\/p>\n<p>We have covered the installation and setup of the AWS Load Balancer Controller, in a different blog. <\/p>\n<p><strong>Refer:<\/strong> <a href=\"https:\/\/devopscube.com\/aws-load-balancer-controller-on-eks\/\" rel=\"noreferrer\">AWS Load Balancer Controller on EKS<\/a><\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\"><b><strong style=\"white-space: pre-wrap;\">Note:<\/strong><\/b> When deploying the AWS Load Balancer Controller for a private EKS cluster, you need to tag the private subnets with the following tag to enable internal load balancer provisioning:<br \/><code spellcheck=\"false\" style=\"white-space: pre-wrap;\">kubernetes.io\/role\/internal-elb: 1<\/code><\/div>\n<\/div>\n<h2 id=\"update-prometheus-service-to-cluster-ip\">Update Prometheus Service to Cluster IP<\/h2>\n<p>For this, we don&#8217;t have to deploy the Prometheus stack with <strong>Node Port<\/strong> service, instead we can use the <strong>Cluster IP<\/strong> service, which is also the default deployment method.<\/p>\n<p>To install the Prometheus stack with default configuration, use the following command.<\/p>\n<pre><code>helm install prometheus prometheus-community\/kube-prometheus-stack -n monitoring --create-namespace<\/code><\/pre>\n<p>Now, we can check the services so that we can make sure the Prometheus components are deployed in ClusterIP services.<\/p>\n<pre><code>kubectl -n monitoring get po,svc<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-108-1.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1755\" height=\"761\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-108-1.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-108-1.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-108-1.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-108-1.png 1755w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Once the AWS Load Balancer deployment is completed, an internal load balancer will automatically be provisioned when we deploy an ingress object.<\/p>\n<p>Note down the Prometheus, Grafana, and Alertmanager service names and port numbers to create the ingress object.<\/p>\n<p>Now, let&#8217;s create an ingress object for the Prometheus stack.<\/p>\n<pre><code>cat &lt;&lt;EOF &gt; ingress.yaml\napiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: monitoring-ingress\n  namespace: monitoring\n  annotations:\n    alb.ingress.kubernetes.io\/scheme: internal  \n    alb.ingress.kubernetes.io\/target-type: ip  \nspec:\n  ingressClassName: alb\n  rules:\n    - host: grafana.techiescamp.com  \n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: prometheus-grafana\n                port:\n                  number: 80\n    - host: prometheus.techeiscamp.com  \n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: prometheus-kube-prometheus-prometheus\n                port:\n                  number: 9090\n    - host: alertmanager.techiescamp.com  \n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: prometheus-kube-prometheus-alertmanager\n                port:\n                  number: 9093\nEOF<\/code><\/pre>\n<p>Here, I have used host names for each of the services, so we can easily remember the names.<\/p>\n<blockquote><p>Note: If you already have a domain in Route53 or GoDaddy, use that one for the application.<\/p><\/blockquote>\n<p>To deploy the Ingress object, use the following command.<\/p>\n<pre><code>kubectl apply -f ingress.yaml<\/code><\/pre>\n<p>To check the Ingress object,<\/p>\n<pre><code>kubectl -n monitoring get ingress<\/code><\/pre>\n<p>To describe the Ingress object.<\/p>\n<pre><code>kubectl -n monitoring describe ingress monitoring-ingress<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-113-2.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1440\" height=\"860\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-113-2.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-113-2.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-113-2.png 1440w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>We can see that the Ingress is successfully created, which means the Internal Load Balancer was also automatically created.<\/p>\n<p>Let&#8217;s open the AWS console and ensure the Load Balancer is properly provisioned.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-114.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1479\" height=\"849\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-114.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-114.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-114.png 1479w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Note down the Internal Load Balancer DNS name for the upcoming configuration.<\/p>\n<p>When we deploy the ingress and Load Balancer creation, a new rule will be added to the EKS cluster security group to expose the Ports of the ingress services.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-117-1.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1528\" height=\"806\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-117-1.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-117-1.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-117-1.png 1528w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>We need to expose these same ports in the OpenVPN server&#8217;s security group.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-118-1.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1319\" height=\"795\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-118-1.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-118-1.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-118-1.png 1319w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h2 id=\"local-dns-resolution-for-ilb\">Local DNS Resolution for ILB<\/h2>\n<p>We can map the DNS records of the AWS Internal Load Balancer to the DNS servers if we have, or for testing purposes we can use the Local DNS resolution.<\/p>\n<p>For this, first we need to identify the IP addresses of the Internal Load Balancer.<\/p>\n<pre><code>nslookup &lt;INTERNAL_LOADBALANCER_DNS_NAME&gt;<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-119-1.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1865\" height=\"750\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-119-1.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-119-1.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-119-1.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-119-1.png 1865w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Copy the IP address and paste it to the <code>\/etc\/hosts<\/code> of your local machine and map the host names that we mentioned in the Ingress object.<\/p>\n<pre><code>sudo vim \/etc\/hosts<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-121.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"2000\" height=\"871\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-121.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-121.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-121.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w2400\/2025\/03\/image-121.png 2400w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>This will help to resolve the DNS query from the local machine.<\/p>\n<blockquote><p>Note: If you are using to map with DNS servers, make sure, you have private hosted zone.<\/p><\/blockquote>\n<p>To access the dashboard, open any of the web browser and paste the hostname.<\/p>\n<h3 id=\"prometheus-dashboard\">Prometheus Dashboard<\/h3>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-122.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1088\" height=\"480\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-122.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-122.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-122.png 1088w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h3 id=\"grafana-dashboard\">Grafana Dashboard<\/h3>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-123.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1090\" height=\"753\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-123.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-123.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-123.png 1090w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h3 id=\"alertmanager-dashboard\">Alertmanager Dashboard<\/h3>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-124.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1088\" height=\"549\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-124.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-124.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-124.png 1088w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>We have implemented the OpenVPN server to access the private EKS resources. This has created an encrypted tunnel over the Internet for secure communication. <\/p>\n<p>This self-hosted VPN Server method is cost-effective for testing and small projects, especially since we are using the open-source version of OpenVPN, which has some limitations.<\/p>\n<p>So if you want to implement for a big project or want the complete benefits, you can go with the enterprise edition or can use the AWS client VPN endpoint solution.<\/p>\n<hr>\n<p><strong>Ngu\u1ed3n:<\/strong> <a href=\"https:\/\/devopscube.com\/private-eks-resources\/\" target=\"_blank\" rel=\"noopener noreferrer\">Access Private EKS Resources Using OpenVPN(complete Guide) \u2014 DevOpsCube<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Source: https:\/\/devopscube.com\/private-eks-resources\/<\/p>\n","protected":false},"author":1,"featured_media":620,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-619","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/619","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=619"}],"version-history":[{"count":0,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/619\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/media\/620"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=619"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=619"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=619"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}